Reputation: 1416
I'm attempting to implement authentication of one single client to my spring boot rest API through X509 - client certification. I've created a private key:
openssl genrsa -des3 -out client.key 1024
To create this key I've set some generic password like changeit
, and this password was used in all subsequent file creations and requests.
Next, I've created a certificate signing request:
openssl req -new -key client.key -out client.csr
and set the common name localhost
(other fields are irrelevant as far as I understand?)
Next, created the certificate using the csr:
openssl x509 -req -days 3650 -in client.csr -signkey client.key -out client.crt
Next, created the Java Truststore:
keytool -import -file client.crt -alias clientCA -keystore truststore.jks
And finally, created the keystore as a .p12 file:
openssl pkcs12 -export -in client.crt -inkey client.key -certfile client.crt -name "clientcert" -out keystore.p12
On the Spring boot(2.0.2 version) side I've got the security configuration class:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.x509();
}
/*
* localhost is the CN of the client certificate
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("localhost")
.password("none")
.roles("USER");
}
}
and the application.properties file:
server.port=8443
logging.level.root=info
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=changeit
server.ssl.trust-store=classpath:truststore.jks
server.ssl.trust-store-password=changeit
server.ssl.client-auth=need
security.headers.hsts=NONE
Submitting a get request like
curl -vkE ./keystore.p12:changeit --cert-type P12 "https://localhost:8443/customers/test"
gives me a valid response (purposely changing or omitting the proper cert throw an SSL error), which is good.
NOW: If I try to submit a POST the same way with a request body, like
curl -kiE ./keystore.p12:changeit --cert-type P12 -X POST -H "Content-Type: application/json" --data @req-body.json "https://localhost:8443/customers"
I get the following response:
HTTP/1.1 403
Set-Cookie: JSESSIONID=106214250C497F20C5F1AA02E554B316; Path=/; Secure; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 16 Jul 2018 13:49:43 GMT
{"timestamp":"2018-07-16T13:49:43.335+0000","status":403,"error":"Forbidden","message":"Forbidden","path":"/customers"}%
I have no clue why this is happening (the 403) and am kindly asking for help.
P.S. Submitting any http method other than GET (even the ones the controller does not support): throws the same 403 - Forbidden.
P.P.S. Calling a non-existent resource with a GET returns a nice proper 404 response. So it has something to do with the HTTP method settings somewhere?
Upvotes: 1
Views: 1805