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/**")
}
}
}
" 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.
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;
}
DefaultTokenServices.class
not set TokenStore
OAuth2RefreshToken refreshToken = tokenStore.readRefreshToken(refreshTokenValue);
if (refreshToken == null) {
throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue);
}
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
}
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.