Spring OAuth2 - Manually creating an access token in the token store

后端 未结 7 949
天涯浪人
天涯浪人 2020-12-07 17:00

I have a situation where I would like to create an access token myself (so not through the usual process). I have come up with something like this:

@Inject
p         


        
7条回答
  •  醉话见心
    2020-12-07 17:48

    Problem

    I had problems with all the implementations listed here, so I finally managed to get my own with a stateless server, oauth2 and google social. Its just the last part of the tutorial that is missing here

    The problem for me is that after executing the google oauth, I need to exchange a 10 second duration token for a long lived token. In order to do that I need to generate a JWT token and exchange it with a real access token generated by myself.

    Implementation

    @Service
    class SocialTokenVerificationService {
    
        @Autowired
        private lateinit var jwsTokenService: JWSTokenService
        @Autowired
        private lateinit var clientDetailsService: ClientDetailsService
        @Autowired
        private lateinit var userService: UserService
        @Autowired
        private lateinit var tokenServices: DefaultTokenServices
        @Autowired
        private lateinit var tokenRequestFactory: OAuth2RequestFactory
    
        fun verifyToken(token: String): OAuth2AccessToken? {
            val claimSet = jwsTokenService.parseToken(token)
            val userDetails = userService.loadUserByUsername(claimSet.subject)
    
            val client = clientDetailsService.loadClientByClientId(DEFAULT_SERVER_CLIENT)
            val parameters = HashMap()
            val authentication = UsernamePasswordAuthenticationToken(userDetails, null, userDetails.authorities)
            return tokenServices.createAccessToken(OAuth2Authentication(
                    tokenRequestFactory.createOAuth2Request(client, TokenRequest(parameters, client.clientId, listOf("read", "write"), "password")),
                    authentication
            ))
        }
    }
    
    • JWSTokenService: its a self implemented class that encodes and decodes the exchanging token between google oauth and mine.
    • ClientDetailsService: bean declared as as part of the authorization server. Comes from my database

      override fun configure(clients: ClientDetailsServiceConfigurer) { clients.jdbc(datasource) }

    • UserService: just a user service that extends UserDetailsService to obtain my users from the database

    • DefaultTokenServices: implemented as a primary bean as follows

      @Bean
      @Primary
      fun tokenServices(): DefaultTokenServices {
          val defaultTokenServices = DefaultTokenServices()
          defaultTokenServices.setTokenStore(tokenStore())
          defaultTokenServices.setSupportRefreshToken(true)
          defaultTokenServices.setTokenEnhancer(jwtAccessTokenConverter())
          return defaultTokenServices
      }
      
    • OAuth2RequestFactory: implemented as a bean as follows

      @Bean
      fun oauthRequestFactory(clientsDetails: ClientDetailsService): OAuth2RequestFactory {
          return DefaultOAuth2RequestFactory(clientsDetails)
      }
      

    With all this dependencies, what I need to do to generate a token that gets stored into the database and follows the same flows as the other ones without providing a password is:

    1. Parse the jws token and verify its validity
    2. Load the user that was authenticated with google
    3. Generate an Authentication using the UsernamePasswordAuthenticationToken class. This is the key part, call DefaultTokenServices#createAccessToken to obtain a new token. It needs some arguments to execute the request:
      • OAuth2Request: it can be created with the OAuth2RequestFactory
      • The Authentication created previously
      • We need to generate a TokenRequest with the client that is triggering this token request. In my case I have that hardcoded

    Summary

    So to recap how to create a token manually:

    • We need to ask the token services to give us a token
    • For that we need to provide the authentication details and a client who does the request
    • With those 2 we can obtain a new token and serve it normally

提交回复
热议问题