Reputation: 51411
I have successfully create a web-service using the spring-boot framework. Now I want to secure my web-service with OAuth2 (using spring) and have a few questions regarding that:
According to my research, spring provides some kind of default-url to request an access token (baseURL/oauth/token
). I have tested the URL using postman, and a valid access token was returned (using client_credentials grant type), but no refresh token. However this method does not work with grant_type=password
and results in the following error response:
{"error":"invalid_grant","error_description":"Bad credentials"}
My spring application logs InvalidGrantException
.
The curl I used to test grant_type=password
is the following:
curl -v -X POST -H "Content-Type: application/json" -H "Authorization: Basic base64encodedclientidandsecret" 'http://localhost:8888/oauth/token?grant_type=password&username=user&password=1234'
I did not test using postman because it does not support grant_type=password
.
How can I get spring to return both accessToken and refreshToken using grant_type=password
?
Is there anything wrong with my configuration?
My spring application (configuration) looks as follows:
@Configuration
@ComponentScan
@EnableAutoConfiguration(exclude = { MongoAutoConfiguration.class, MongoDataAutoConfiguration.class })
@SpringBootApplication
public class CsWebServerApplication {
public static final String RESOURCE_ID = "myresource";
public static final String CLIENT_ID = "myapplication";
public static final String CLIENT_SECRET = "application_secret";
public static void main(String[] args) {
SpringApplication.run(MyWebServerApplication.class, args);
}
@Configuration
@EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Inject
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient(CLIENT_ID)
.authorizedGrantTypes("client_credentials", "password", "refresh_token")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust")
.secret(CLIENT_SECRET);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
super.configure(oauthServer);
}
}
@Configuration
@EnableResourceServer
protected static class ResourceConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/*", "/admin/beans").and().authorizeRequests().anyRequest()
.access("#oauth2.hasScope('read')");
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(RESOURCE_ID);
}
}
@Configuration
@EnableWebSecurity
protected static class WebConfigurer extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
}
@Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity.ignoring()
// All of Spring Security will ignore the requests
.antMatchers("/accessibleservices/**")
}
}
}
Upvotes: 4
Views: 7456
Reputation: 1
pom.xml add
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
add config
@Configuration
public class RedisTokenStoreConfig {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public TokenStore redisTokenStore (){
return new RedisTokenStore(redisConnectionFactory);
}
}
in your OAuth2Config
@Autowired
@Qualifier("redisTokenStore")
private TokenStore tokenStore;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userService)
.tokenStore(tokenStore);//set tokenStore
}
Upvotes: 0
Reputation: 1
DefaultTokenServices.class
not set TokenStore
OAuth2RefreshToken refreshToken = tokenStore.readRefreshToken(refreshTokenValue);
if (refreshToken == null) {
throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue);
}
Upvotes: 0
Reputation: 2610
About supporting of refresh tokens. By default spring oauth using DefaultTokenServices class and support of refresh tokens disabled by default. You should override its initialization in your OAuth2Config.class.
Example:
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
return tokenServices;
}
Upvotes: 0
Reputation: 19001
"4.3.2. Access Token Request" in RFC 6749 (The OAuth 2.0 Authorization Framework) says as follows.
The client makes a request to the token endpoint by adding the following parameters using the "application/x-www-form-urlencoded" format per Appendix B with a character encoding of UTF-8 in the HTTP request entity-body:
So, -H "Content-Type: application/json"
is wrong. In addition, your curl command line is wrong. Use -d
option to specify a form parameter for POST.
Upvotes: 3