I am trying to go through spring security 6 and set up oauth2. To get a token i am trying to use the client_secret_jwt
authentication mechanism for client.
But after a lot of tries I have been unable to do so.
This is my code for registering client:
@Bean
public RegisteredClientRepository registeredClientRepository() {
RegisteredClient registeredClient =
RegisteredClient
.withId(UUID.randomUUID().toString())
.clientId("client")
.clientSecret("secret_secret_secret_secret_secret")//.tokenSettings()
.clientAuthenticationMethod(
ClientAuthenticationMethod.CLIENT_SECRET_JWT)
.clientSettings(ClientSettings.builder()
.tokenEndpointAuthenticationSigningAlgorithm(SignatureAlgorithm.RS256)
.jwkSetUrl("http://localhost:8080/oauth2/jwks")
.build())
.authorizationGrantType(
AuthorizationGrantType.CLIENT_CREDENTIALS)
.redirectUri("https://www.manning.com/authorized")
//.clientSettings(ClientSettings.builder().build())
.scope("CUSTOM")
.build();
return new InMemoryRegisteredClientRepository(registeredClient);
}
This is my code for generating a jwt token signed using the secret key defined above.
@Bean
public JWKSource<SecurityContext> jwkSource()
throws NoSuchAlgorithmException {
/* A different method */
JWKSet jwkSet = new JWKSet(rsaKey);
try {
//printing a token at startup
String assertion = getJWTToken("client");
logger.info("Created assertion: "+assertion);
} catch (Exception e) {
logger.info("Error creating assertion: "+e.getLocalizedMessage());
e.printStackTrace();
}
return new ImmutableJWKSet<>(jwkSet);
}
private String getJWTToken(String username) {
//using the secret key
String secretKey = "secret_secret_secret_secret_secret";
String token = Jwts.builder()
.subject(username)
.issuer(username)
.id(UUID.randomUUID().toString())
.audience().add("http://localhost:8080/oauth2/token").and()
.issuedAt(new Date(System.currentTimeMillis()))
.expiration(new Date(System.currentTimeMillis() + 600*1000))
.signWith(Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8))).compact();
return token;
}
I am using the assertion printed at the start to call the token api, but have been unable to acquire a token after trying a gazillion variations.
This is the curl call i think is the one i am supposed to use
curl -X POST -v\
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJjbGllbnQiLCJpc3MiOiJjbGllbnQiLCJqdGkiOiIxMjI0NmM4ZC0xZmIxLTRkM2UtODI2NC05OWRhNmYzNTA1NGIiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4MDgwL29hdXRoMi90b2tlbiJdLCJpYXQiOjE3MDc2MzM0ODcsImV4cCI6MTcwNzYzNDA4N30.eYk7T67ue4KrqZqf3Rk06HqwEPRRXpYGSzkbWXtv7zo" \
http://localhost:8080/oauth2/token
This is the response i keep getting
* Trying [::1]:8080...
* Connected to localhost (::1) port 8080
> POST /oauth2/token HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.4.0
> Accept: */*
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 406
>
< HTTP/1.1 400
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 0
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 11 Feb 2024 06:39:31 GMT
< Connection: close
<
{"error":"invalid_request"}* Closing connection
I am not sure what i am missing or doing wrong. Have not been able to find any example on the internet.
I have been able to get the credentials using both basic and post secret methods.
Edit--- Dug some more and found that there is an exception while client authentication
Caused by: com.nimbusds.jose.proc.BadJOSEException: Signed JWT rejected: Another algorithm expected, or no matching key(s) found
at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:357) ~[nimbus-jose-jwt-9.37.3.jar:9.37.3]
at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:303) ~[nimbus-jose-jwt-9.37.3.jar:9.37.3]
at org.springframework.security.oauth2.jwt.NimbusJwtDecoder.createJwt(NimbusJwtDecoder.java:158) ~[spring-security-oauth2-jose-6.2.1.jar:6.2.1]
... 126 common frames omitted
I am definitely missing some configurations.
So after putting almost the whole day on it, i was able to obtain the token.
2 changes:
.clientSettings(ClientSettings.builder()
.tokenEndpointAuthenticationSigningAlgorithm(MacAlgorithm.HS256)//not rs256
.jwkSetUrl("http://localhost:8080/oauth2/jwks")
.build())
curl -X POST -v -H \
"Content-Type: application/x-www-form-urlencoded"\
-d "client_id=client&grant_type=client_credentials&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJjbGllbnQiLCJpc3MiOiJjbGllbnQiLCJqdGkiOiIxNDdlMTU5YS05YjU3LTQ4NWMtYTM5Ni1hYzAxOGMyOThmZDkiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4MDgwL29hdXRoMi90b2tlbiJdLCJpYXQiOjE3MDc2NDk2OTEsImV4cCI6MTcwNzY1NTY5MX0.J8G_luq7SMCbyaK_ykRtYdc9h-xEJhyi4RRTuH15w7I" \
http://localhost:8080/oauth2/token