Reputation: 305
[PLEASE SEE UPDATE SETION BELOW FOR LATEST ITERATION]
I am trying to set up a Spring Boot REST application using Spring Security. Our front-end is authenticating our users with OIDC in Okta, and is passing the JWT in the Authorization Bearer token. Okta is using PKCE.
I am referencing the following example, and it seems to be a very simple setup: https://docs.spring.io/spring-security-oauth2-boot/docs/current/reference/html/boot-features-security-oauth2-resource-server.html
Our Spring Boot application is only going to be a Resource Server, so I think I only need to follow the directions in sections 2.1 to 2.2.3. I have @EnableResourceServer
in my application, and I have the following in my application.yml
:
spring:
security:
oauth2:
resource:
jwt:
key-set-uri: https://dcsg-hub-dev.okta.com/oauth2/v1/keysZ?client_id=???
When I call my app using Postman, I am getting a 401 error:
{
"error": "invalid_token",
"error_description": "Invalid access token: eyJraWQ..."
}
It shows the valid token, which I can verify by calling the Okta userinfo
endpoint. Unfortunately, it does not give me any other information.
I ended up setting breakpoints in the org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter
class. Stepping into the code called from this location, the error is being caused at code in org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager
:
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (authentication == null) {
throw new InvalidTokenException("Invalid token (token not found)");
} else {
String token = (String)authentication.getPrincipal();
OAuth2Authentication auth = this.tokenServices.loadAuthentication(token);
if (auth == null) {
throw new InvalidTokenException("Invalid token: " + token);
Which calls the following code in the same class:
public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException, InvalidTokenException {
OAuth2AccessToken accessToken = this.tokenStore.readAccessToken(accessTokenValue);
if (accessToken == null) {
throw new InvalidTokenException("Invalid access token: " + accessTokenValue);
It seems that the code is using the token itself as a key to retrieve the token from a hash map. As you can see above, it is using getPrincipal()
to get the 'token'. It seems to me it thinks the token should be a user ID, which it is trying to use to find the user's token. It seems odd that it is using the token as a key to get the value, when the value is already there.
Any ideas?
<<<<<<<<<<<<<< UPDATE >>>>>>>>>>>>>>>
I followed the doc in this link: https://github.com/spring-projects/spring-security/tree/5.2.1.RELEASE/samples/boot/oauth2resourceserver-jwe
My application.yml
now looks like this:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://dcsg-hub-dev.okta.com
jwk-set-uri: https://dcsg-hub-dev.okta.com/oauth2/v1/keys?client_id=
This is now definitely calling the JWK URI, whereas before it wasn't. However, now I am getting the following error:
Caused by: com.nimbusds.jose.proc.BadJOSEException: Signed JWT rejected: Another algorithm expected, or no matching key(s) found
I set breakpoints in that code, and for whatever reason, the kid
that comes back in the token/JWT from Okta does not match any of the keys that are in the Okta jwk-set-uri
.
Upvotes: 2
Views: 1266
Reputation: 305
I found out from Okta that this feature is not supported, you need to create your own authorization server with API Access Management.
Upvotes: 1