Westy
Westy

Reputation: 305

Problems using Spring Security with an Okta OIDC JWT

[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

Answers (1)

Westy
Westy

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

Related Questions