ImplicitAudienceValidatingTokenServices missing from new okta-spring-boot 2.1.1

Viewed 130

I have upgraded our Spring Boot apps from using okta-spring-boot-starter v0.61 to v2.1.1

The microservices are now always throwing:

p.a.OAuth2AuthenticationProcessingFilter : Authentication request failed: error="invalid_token", error_description="Invalid access token:  ... TOKEN OMITTED

The NEW (v2.1.1) OAuth2AuthenticationManager is wired with an an instance of org.springframework.security.oauth2.provider.token.DefaultTokenServices which has an empty hashmap and causes an exception (because OAuth2AuthenticationManager gets null back) from tokenServices.loadAuthentication(token)

The OLD (v0.61) implementation used an instance of com.okta.spring.oauth.implicit.ImplicitAudienceValidatingTokenServices

This was created automatically in the old code inside ResourceServerConfig

ImplicitAudienceValidatingTokenServices is now gone from okta-spring-boot and so is ResourceConfig. It's not clear to me how I would enable the same behavior in Okta Spring Boot Starter v2.1.1.

Any ideas on what config/properties I am missing to restore the old behavior? I don't believe Okta even supports 'remote token validation' (not sure on the exact correct technical phrase). Local validation remains fine for our purposes.

2 Answers

A lot changed between those versions. The biggest of was Spring Security's OAuth support (which the Okta lib sits on top of). Make sure you don't have the old Spring Sec lib on your classpath spring-security-oauth. The related migration guide might help you too (depending on what you are doing).

From here there are two things to configure:

  1. Your config properties (those should remain the same okta.oauth2.*
  2. Configuring the resource server.

For the last one, all that's left is to us the new Spring Security API to configure a resource server:

import com.okta.spring.boot.oauth.Okta;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class OAuth2ResourceServerSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
            // all requests are authenticated
            .anyRequest().authenticated()
            .and()
            .oauth2ResourceServer().jwt(); // replace .jwt() with .opaqueToken() for Opaque Token case

        // Send a 401 message to the browser (w/o this, you'll see a blank page)
        // this is optional, and only needed if people are accessing your API manually through a browser
        Okta.configureResourceServer401ResponseBody(http);
    }
}

You can see a full example here: https://github.com/okta/samples-java-spring/blob/master/resource-server/src/main/java/com/okta/spring/example/ResourceServerExampleApplication.java (just add your properties)

The Okta-specific bits are wired in and configured automatically, for example, Okta-specific JWT validation (there is no official JWT access token spec, yet).

Also, for the "remote token validation", it's referred to as "opaque" in the Spring Sec API, see the comment in the code block for .opaueToken().

As mentioned, I was able to solve the issue.

With the example above, I also found one other. The first one was more specific to general Spring: https://github.com/spring-projects/spring-security-samples/blob/main/servlet/spring-boot/java/oauth2/resource-server/hello-security/src/main/java/example/OAuth2ResourceServerSecurityConfiguration.java

Since I am using okta-spring-boot, I used the example from Brian: https://github.com/okta/samples-java-spring/blob/master/resource-server/src/main/java/com/okta/spring/example/ResourceServerExampleApplication.java

The first thing I did was add two new properties for Spring Boot. This is confusing because I believe the names of the same properties have changes very subtly at least once over different versions of Spring. There are examples with it different ways which will turn up on Google and not be immediately noticeable as different. These are correct for Spring Boot 2.5.4 and Spring Core 5.3.9:

spring.security.oauth2.resourceserver.jwt.issuer-uri: https://your domain.okta.com/oauth2/your_auth_server_id (might need /default depending on how your app is setup)

spring.security.oauth2.resourceserver.jwt.jwk-set-uri: url_above/v1/keys

I had to remove @EnableResourceServer and added (based on the Okta example above) the annotation @EnableGlobalMethodSecurity(prePostEnabled = true, secureEnabled = true)

In my case we had an implementation of ResourceServerConfigurerAdapter that I updated to instead extend WebSecurityConfigurerAdapter and used the API to create the Resource Server: .and().oauth2ResourceServer().jwt();

I need to still do further testing and want to understand the options on EnableGlobalMethodSecurity, but for the moment my REST endpoints will accept Bearer tokens properly again.

Related