Search code examples
spring-bootspring-security-oauth2okta

ImplicitAudienceValidatingTokenServices missing from new okta-spring-boot 2.1.1


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.


Solution

  • 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().