Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
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;
not set TokenStore
OAuth2RefreshToken refreshToken = tokenStore.readRefreshToken(refreshTokenValue);
if (refreshToken == null) {
throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue);
<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
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.