1

Currently I am using spring security with OAuth 2.0 enabled and everything is in place and working fine!

http://localhost:8080/SpringSecurityOAuth2Example/oauth/token?grant_type=password&username=kalynpradhan@gmail.com&password=abc

I send the client credentials in request header as shown above i.e. username=kalynpradhan@gmail.com and password=abc

Can I send the OAuth 2.0 configuration in request body instead of request header?

Is there any configuration by which I can make the OAuth in spring accept the tokens in request body?

below is my configuration files for spring security using OAuth 2.0

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    private static String REALM = "MY_OAUTH_REALM";

    /*
     * The token store is the store where all the tokens are stored, It can be
     * InMemory, JDBC, etc.
     */
    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private UserApprovalHandler userApprovalHandler;

    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    /**
     * SpringData JPA dataSource injected.
     */
    @Autowired
    private DataSource dataSource;

    /**
     * Autowiring the {@link CustomUserDetailsService} for configuring the
     * {@link UserDetailsService} which provides the required user details to
     * the security context.
     * 
     * This extra implementation of the userDetailsService is necessary because
     * after OAuth 2.0 version - 2.0.10.RELEASE the UserDetails service is not
     * automatically extracted from the context.
     * 
     * Here is a link to the documentation in the gitHub community. <a href=
     * "https://github.com/royclarkson/spring-rest-service-oauth/issues/19">
     * Documentation</a>
     */
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //@formatter:off
        clients.jdbc(dataSource);/*.withClient("my-trusted-client")
                .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
                .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT").scopes("read", "write", "trust").secret("secret")
                .accessTokenValiditySeconds(120).// Access token is only valid for 2 minutes.
                refreshTokenValiditySeconds(600);// Refresh token is only valid for 10 minutes.
        //@Formatter:on
*/  }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
                .authenticationManager(authenticationManager).userDetailsService(userDetailsService);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.realm(REALM + "/client");
    }
}

WebSecurityConfigurerAdapter config

@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private ClientDetailsService clientDetailsService;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private AuthenticationProvider authenticationProvider;

    /**
     * Defines custom authentication provider.
     */
    @Override
    protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
        authManagerBuilder.authenticationProvider(authenticationProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().anonymous().disable().authorizeRequests().antMatchers("/oauth/token").permitAll();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/students/**");
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

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

    @Bean
    @Autowired
    public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore) {
        TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
        handler.setTokenStore(tokenStore);
        handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
        handler.setClientDetailsService(clientDetailsService);
        return handler;
    }

    /**
     * This Approval store is used to direct the OAuth server to use the
     * tokenStore that is exposed as a spring bean and uses the database to
     * store all the tokens.
     * 
     * @param tokenStore
     * @return The Approval store which uses the tokenStore injected into the
     *         spring context as a bean.
     * @throws Exception
     */
    @Bean
    @Autowired
    public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
        TokenApprovalStore store = new TokenApprovalStore();
        store.setTokenStore(tokenStore);
        return store;
    }
}

The Resource server configuration

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    private static final String RESOURCE_ID = "my_rest_api";

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId(RESOURCE_ID).stateless(false);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.anonymous().disable().requestMatchers().antMatchers("/user/**").and().authorizeRequests()
                .antMatchers("/user/**").access("hasRole('ADMIN')").and().exceptionHandling()
                .accessDeniedHandler(new OAuth2AccessDeniedHandler());
    }

}
Kalyan Pradhan
  • 1,415
  • 3
  • 19
  • 34

1 Answers1

1

you have overriden configure method from AuthorizationServerConfigurerAdapter:

@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    oauthServer.realm(REALM + "/client");
}

try to use this:

@Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.allowFormAuthenticationForClients().realm(REALM + "/client");
    }
hi_my_name_is
  • 4,894
  • 3
  • 34
  • 50
  • Okay, I tried and added username and password in request body, – Kalyan Pradhan Oct 20 '16 at 07:58
  • But { "username": "kalynpradhan@gmail.com", "password": "abc" } This is the error, thats probably because OAuth is expecting the username and password in header. Is there any way to tell spring security and OAuth that credentials will come in request body and not in header? – Kalyan Pradhan Oct 20 '16 at 07:58
  • first of all you seems to not sending it in header, but in query (URL) now. Didnt adding 'allowFormauthentication..' change anything? – hi_my_name_is Oct 20 '16 at 08:02
  • Should I try for Authentication filter, Anyways thanks for pointing this out!! – Kalyan Pradhan Oct 20 '16 at 08:03
  • Yep, it changed the way I used to send the credentials, but I wish to send the credentials in request body in a json format – Kalyan Pradhan Oct 20 '16 at 08:04
  • Example : { "email":"email", "password":"password" } – Kalyan Pradhan Oct 20 '16 at 08:04
  • Any Idea how to do that? by the way thanks for pointing out the `allowFormAuthenticationForClients()` I was unaware of this – Kalyan Pradhan Oct 20 '16 at 08:06
  • org.springframework.security.oauth2.common.AuthenticationScheme is an enum which shows what types are possible, its used from client perspective, but you need to 1st enable it on AuthorizationServerSide ( hopefully 'allow..' method did that + we need to figure out how to use json :) – hi_my_name_is Oct 20 '16 at 08:06
  • seems its not so easy, but possible - http://stackoverflow.com/questions/38165131/spring-security-oauth2-accept-json – hi_my_name_is Oct 20 '16 at 08:08
  • Okay great! that enum would help me a lot, thanks, I have used enums previously by using `http.addFilterBefore(authFilter(), UsernamePasswordAuthenticationFilter.class);` and authFilter contains a mechanism of handling the jsons by extending `AbstractAuthenticationProcessingFilter` – Kalyan Pradhan Oct 20 '16 at 08:11
  • Thanks, this helped me to get it correct!, I would like to accept your answer as the correct one, thank you! And please like and edit my question if you liked it, and you can suggest me some suggestions – Kalyan Pradhan Oct 20 '16 at 08:13