Reputation: 125
I have setup an OAuth2 auth server with the main purpose of using an authorization code flow. From what I can gather, the flow is working as I'm able to get a valid access_token at the end of the flow but the problem is I'm not getting a request_token response field. I'm not sure if I'm meant to do something differently to what I've done, but I believe all I had to do to get this was to add "request_token" in the authorizedGrantTypes parameters (which I have done). I will most the relevant setup code below.
AuthorizationServerConfigurerAdapter
@Import(AuthorizationServerEndpointsConfiguration.class)
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
PasswordEncoder passwordEncoder;
AuthenticationManager authenticationManager;
KeyPair keyPair;
RedisConnectionFactory redisConnectionFactory;
public AuthorizationServerConfig(AuthenticationManager authenticationManager, KeyPair keyPair, RedisConnectionFactory redisConnectionFactory,
PasswordEncoder passwordEncoder) {
this.keyPair = keyPair;
this.redisConnectionFactory = redisConnectionFactory;
this.authenticationManager = authenticationManager;
this.passwordEncoder = passwordEncoder;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("web")
.secret(passwordEncoder.encode("noonewilleverguess"))
.scopes("resource:read", "resource:write")
.authorizedGrantTypes("authorization_code", "refresh_token")
.redirectUris("http://localhost:8080/login-two");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.tokenStore(tokenStore(redisConnectionFactory))
.accessTokenConverter(accessTokenConverter());
}
@Bean
public TokenStore tokenStore(RedisConnectionFactory redisConnectionFactory) {
return new RedisTokenStore(redisConnectionFactory);
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setKeyPair(this.keyPair);
return converter;
}
}
AuthorizationServerSecurityConfiguration
@Configuration
public class JwtSetEndpointConfiguration extends AuthorizationServerSecurityConfiguration {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.requestMatchers()
.mvcMatchers("/.well-known/jwks.json")
.and()
.authorizeRequests()
.mvcMatchers("/.well-known/jwks.json").permitAll();
}
}
WebSecurityConfigurerAdapter
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
protected UserDetailsService userDetailsService() {
return new UserDetailsServiceImpl();
}
@Bean
public KeyPair keyPairBean() throws NoSuchAlgorithmException {
//TODO:drt - probs change
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
gen.initialize(2048);
return gen.generateKeyPair();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
}
@Bean
PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
The authorization code flow response
I first send a GET request to:
http://localhost:8080/oauth/authorize?response_type=code&client_id=web&state=8781487s1
Example Redirection: http://localhost:8080/login-two?code=N-U9XJ&state=8781487s1
So then I send a POST request to http://localhost:8080/oauth/token with Basic Auth
This is the example response I'm receiving, with no refresh_token field :
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MTc2MjY1NzQsInVzZXJfbmFtZSI6ImFkbWluIiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6ImRENUplcWI3QlhHTkd0WkI1QVU4akhNbGR1YyIsImNsaWVudF9pZCI6IndlYiIsInNjb3BlIjpbInJlc291cmNlOndyaXRlIiwicmVzb3VyY2U6cmVhZCJdfQ.D5XKotYYAZkKtZNWdD-wirtoi3prU3CCmibIiQF5kodbXeK5ETdZ5k8CgSBLd7Aq-XEdhYXUEbtzzI0vf1vHf_MyhPFy_owldm_JJf2-2z9jNoU2BSnGMp6TCM00pCSMwbk57paLRZouryHEhTdvixVDmez2e1KmMVmXP6NypARB3Sp5SD2sZ2JN7FBQdkQ0OMVChjAQMTy1M3mDiT5dpT7iD7JxKRFTmD7qKYSF_gbQi6mEF3oH4j40TGI_CpyP3kKdDh4kiEfNeFd84YNHGYZACsYHfjoJrtJV1ECoeLph5CpmSpzt0lhOlzy8Q98OsPR8SdRt5Ou9N-BFmftZDw",
"token_type": "bearer",
"expires_in": 13462,
"scope": "resource:write resource:read",
"jti": "dD5Jeqb7BXGNGtZB5AU8jHMlduc"
}
Hopefully one of you guys can help, as at this point after trying things out and looking up online I've no idea what I'm doing wrong. Please help,
Upvotes: 0
Views: 1084
Reputation: 125
So I managed to fix this so it now returns a refresh token after the authorization flow. All I had to do was add the DefaultTokenServices bean and make sure to setSupportRefreshToken to true.
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
Upvotes: 1