1

So far I've had the password grant type and that worked perfectly fine. Recently I started implementing the Authorization code grant of OAuth in my project. I'm able to get the authorization code from the server. Using the code I'm again able to get the access-token.

The problem is I'm unable to reach the resource server using my access-token. I'm getting redirected to Spring's default /login page everytime I try to access any resource.

Below is the Resource Server:

@Configuration
@PropertySource("classpath:webservices-application.properties")
@EnableResourceServer
public class ResourceServer extends ResourceServerConfigurerAdapter{

    @Value("${security.oauth2.resource.id}")
    private String resourceId;

    @Bean
    public JdbcTokenStore getTokenStore() {
        return new JdbcTokenStore(dataSource);
    }

    @Autowired
    private DataSource dataSource;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/oauth/**","/login","/").permitAll()
                .anyRequest().authenticated();
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenStore(getTokenStore())
                .resourceId(resourceId).stateless(false);
    } 
} 

WebSecurity:

@Configuration
@EnableWebSecurity
@EnableOAuth2Sso
public class CustomWebsecurity extends WebSecurityConfigurerAdapter {
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/oauth/**","/login","/").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin();
    }
} 

The AuthorizationServer:

@Configuration
@EnableAuthorizationServer
@EnableOAuth2Sso
protected class AuthorizationApplication extends AuthorizationServerConfigurerAdapter {

    @Autowired
    public AuthorizationApplication (ApplicationContext applicationContext, AuthenticationManager authenticationManager) {
        this.passwordEncoder = applicationContext.getBean(PasswordEncoderImpl.class);
        this.authenticationManager = authenticationManager;
    }

    private PasswordEncoder passwordEncoder;

    private AuthenticationManager authenticationManager;

    @Bean
    protected AuthorizationCodeServices getAuthorizationCodeServices() {
        return new JdbcAuthorizationCodeServices(dataSource);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        AuthorizationCodeServices services = getAuthorizationCodeServices();
        JdbcTokenStore tokenStore = getTokenStore();
        endpoints
                .userDetailsService(userDetailsService)
                .authorizationCodeServices(services)
                .authenticationManager(authenticationManager)
                .tokenStore(tokenStore)
                .approvalStoreDisabled();
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients();
        security.passwordEncoder(passwordEncoder);
    }
}

The issue might be because of some incorrect configuration of the WebSecurity class. But, I've tried multiple configurations with no luck.

Akeshwar Jha
  • 4,516
  • 8
  • 52
  • 91
  • Why you used `approvalStoreDisabled()` inside `AuthorizationServerConfigurerAdapter` ?? – Ataur Rahman Munna Mar 04 '18 at 11:49
  • I don't need to implement granular permissions as of now, so disabled it. But this shouldn't be an issue, right? – Akeshwar Jha Mar 04 '18 at 12:02
  • I think somehow authorization server can not verify your access token. This may be a help https://stackoverflow.com/questions/29596036/spring-security-oauth2-resource-server-always-returning-invalid-token – Ataur Rahman Munna Mar 04 '18 at 12:09
  • I checked out the other question. My issue is a bit different. My `ResourceServer` and `AuthorizationServer` are getting the same token reference because I was able to access the resources through the password grant type. The problem in my case is the redirection to the login endpoint even with a correct token. It seems more like a configuration issue. That too, most probably due to the `WebSecurityConfigurerAdapter` class, which I've recently added. – Akeshwar Jha Mar 04 '18 at 19:17
  • Just to secure the `authorize` endpoint. I cannot find a place to add `EnableOAuth2Sso`. Annotating the AuthorizationServer or ResourceServer or both with `EnableOAuth2Sso` is giving me an error: `HTTP URL must not be null`, whenever I'm trying to access a resource. Similar to the error reported here: https://github.com/spring-guides/tut-spring-boot-oauth2/issues/10#issuecomment-249454159 Do you have any clue why this error might be occuring? I've already added `formLogin()` to the configure method of the ResourceServer after removing the WebSecurity class. – Akeshwar Jha Mar 04 '18 at 21:35
  • Incase someone came here looking for [this](https://stackoverflow.com/a/57557022/1581226) – qwerty Aug 22 '19 at 08:58

1 Answers1

0

With some guidance from @dur, I was able to reach to the solution. Here's one of the culprits:

The default order of the OAuth2 resource filter has changed from 3 to SecurityProperties.ACCESS_OVERRIDE_ORDER - 1. This places it after the actuator endpoints but before the basic authentication filter chain. The default can be restored by setting security.oauth2.resource.filter-order = 3

All in all, I made the following changes:

  1. Used @EnableOauth2Client instead of @EnableOAuth2Sso at the ResourceServer as well as the AuthorizationServer, because the latter was giving me the following error:

    java.lang.IllegalArgumentException: URI must not be null
    
  2. Removed CustomWebSecurity and did all the security configurations in the ResourceServer itself.

  3. Change the filter order of the Resource filter by putting the following in the properties file:

    security.oauth2.resource.filter-order = 3
    
  4. Some basic change in the security configuration.


Here's my ResourceServer class now:

@Configuration
@PropertySource("classpath:webservices-application.properties")
@EnableResourceServer
@EnableOAuth2Sso
public class ResourceServer extends ResourceServerConfigurerAdapter{

    @Value("${security.oauth2.resource.id}")
    private String resourceId;

    @Bean
    public JdbcTokenStore getTokenStore() {
        return new JdbcTokenStore(dataSource);
    }

    @Autowired
    private DataSource dataSource;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .requestMatchers().antMatchers(
                "/protected_uri_1",
                "/protected_uri_2",
                "/protected_uri_3")
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
        .and().formLogin();
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenStore(getTokenStore())
                .resourceId(resourceId);
    }

}
Akeshwar Jha
  • 4,516
  • 8
  • 52
  • 91
  • Do you maybe have a full project example you can put on GitHub? I'm starting from scratch and your configuration still does not work. Authentication endpoints work to get the access_token via password or authorization_code grant but protecting the API endpoints does not work at all :( – dst Jun 25 '18 at 13:28