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
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.
@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:
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 OAuth2RequestFactoryAuthentication created previouslyTokenRequest with the client that is triggering this token request. In my case I have that hardcodedSo to recap how to create a token manually: