简体   繁体   中英

JWT bearer exchange for access token request using Spring Security OAuth2

I have a working setup that includes:

  • Authorization Service (AS)
  • Resource Service (RS)
  • Relying Party (RP)

Implementation is based on Spring Boot with Spring Security (OAuth2). I have the following working 2LA flow:

  1. RP is able to send a request for an access token to AS using client_secret and grant_type=client_credentials .
  2. AS responds with an access token to RP.
  3. RP is able to make an authorized request to RS using said access token.
  4. RS is able to verify the access token using /check_token endpoint on AS.

Question What changes do I need to make to my AS that it accepts JWT based request for an access token in step 1 above?

Note that I don't need a JWT based access token. Only the initial request by the RP to the AS for an access token should be a JWT based request.

Related question: How to use Spring OAuth2 JWT Token?

Clarification I'd like to know what code I need to write in order to accept a JWT from RP using Spring Security OAuth2 library. Where do I add RP's public key to AS and where do I add RP's private key to the OAuth2 rest template?

RP OAuth2 Client Configuration:

@Configuration
@EnableOAuth2Client
open class OAuth2ClientConfiguration {

    val tokenUrl = "http://localhost:8180/oauth/token"

    @Bean
    open fun resource(): OAuth2ProtectedResourceDetails {
        return ClientCredentialsResourceDetails().apply {
            clientId = "demo-rp"
            clientSecret = "rp-secret"
            grantType = "client_credentials"
            scope = listOf("quotes")
            accessTokenUri = tokenUrl
        }
    }

    @Bean
    open fun restTemplate(): OAuth2RestOperations {
        return OAuth2RestTemplate(
                resource(),
                DefaultOAuth2ClientContext(DefaultAccessTokenRequest()))
    }

}

AS OAuth2 Configuration:

@Configuration
@EnableAuthorizationServer
open class OAuth2Configuration : AuthorizationServerConfigurerAdapter() {

    @Autowired
    val authenticationManager: AuthenticationManager? = null

    override fun configure(security: AuthorizationServerSecurityConfigurer) {
        // @formatter:off
        security
        .tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')")
        .checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')")
        // @formatter:on
    }

    override fun configure(clients: ClientDetailsServiceConfigurer) {
        // @formatter:off
        clients.inMemory()
        .withClient("demo-rp")
            .authorizedGrantTypes("client_credentials")
            .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
            .scopes("quotes")
            .secret("rp-secret")
            .accessTokenValiditySeconds(60)
        .and()
        .withClient("demo-rs")
            .authorizedGrantTypes("client_credentials")
            .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
            .secret("rs-secret")
            .accessTokenValiditySeconds(60)
        // @formatter:on
    }

    override fun configure(endpoints: AuthorizationServerEndpointsConfigurer) {
        // @formatter:off
        endpoints
        .authenticationManager(authenticationManager)
        // @formatter:on
    }
}

I ended up using Nimbus OAuth2 SDK to write a client that sent a JWT based request for access token. This is part of the RP.

In AS, I added a JwtTokenEndpointAuthenticationFilter that inspects ServletRequest and performs authentication using a hand-written AuthenticationProvider .

Example AS code here . Example RP code here .

Inspiration for this solution came from here .

Note that I don't need a JWT based access token. Only the initial request by the RP to the AS for an access token should be a JWT based request.

OAuth 2.0 components interactions in each flow are identical regardless of what type of Access Token will be generated. For example, in a Password Grant flow, client send a request to the Authorization Server and gets an Access Token, if he was lucky. The fact that Authorization Server used an In-Memory Token or JWT ones or Persisted tokens are not changing the interactions in this particular flow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM