Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to secure a MVC application with OAuth2 using Spring?

Sorry, my English.

I have an application I can login in the usual way.

@Configuration
@EnableWebSecurity
public class LoginSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        System.out.println("LoginSecurityConfig :: configure");

        auth.jdbcAuthentication().dataSource( getDataSource() )
            .passwordEncoder( new BCryptPasswordEncoder(16) )
            .usersByUsernameQuery(
                "select user_name as username,password,enabled from users where user_name=?")
            .authoritiesByUsernameQuery(
                "select user_name as username, role_name from users_roles ur join users u on ur.user_id = u.user_id and u.user_name = ?");

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {


        http
        .csrf().disable()
        .authorizeRequests()
        .antMatchers("/login*").anonymous()
        .antMatchers("/resources/**").permitAll()
        .antMatchers("/fotos/**").permitAll()
        .antMatchers("/users").access("hasRole('ROLE_ADMIN')")
        .antMatchers("/user").access("hasRole('ROLE_ADMIN')")
        .anyRequest().authenticated()
        .and()

        .formLogin()
        .loginPage("/loginPage")
        .defaultSuccessUrl("/home", true)
        .failureUrl("/loginPage?error=true")
        .loginProcessingUrl("/login")
        .usernameParameter("username")
        .passwordParameter("password")
        .and()

        .logout()
        .logoutSuccessUrl("/loginPage")
        .invalidateHttpSession(true); 



    }    

}

Using this I can try to access any secured resource and the system sends me to the loginPage where I can post username and password to the internal login controller then I have the Principal and can access the secured resources ( home, users, user ). Working fine.

But... I need to remove the user control database stuff and use OAuth2 to allow the same kind of access. I don't want to have any users in my database anymore. I need a login screen and then a token request like http://myserver/oauth/token?grant_type=password&username=admin&password=admin passing client_id and client_secret in Basic. I know how to do the "get token" part and my server is working fine and give me the token and refresh token but only using Postman because I have no idea how to use it in my web application code. All tutorials I've found are using both Server and Client in the same application and actually don't show how to consume an OAuth2 remote server.

Already try to use this. It is an excellent tutorial and very near to what I need but too complex to me.

I have this code and understand it can use the server and issue a token using the client credentials, but don't know how to give to the user a login screen and take his credentials to complete the request (the GET part).

@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfigRemoteTokenService extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(final HttpSecurity http) throws Exception {
                http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                    .and()
                    .authorizeRequests().anyRequest().permitAll();              
    }

    @Primary
    @Bean
    public RemoteTokenServices tokenServices() {
        final RemoteTokenServices tokenService = new RemoteTokenServices();
        tokenService.setCheckTokenEndpointUrl("http://myoauthserver/oauth/check_token");
        tokenService.setClientId("clientid");
        tokenService.setClientSecret("password");
        return tokenService;
    }

}

so... how can I secure my system, take login and password from the user and use this code to control credentials like I was using usual database method?

Or OAuth2 is only for secure REST API?

enter image description here

Please be newbie friendly because I'm not very comfortable using Spring.

like image 930
Magno C Avatar asked May 30 '18 03:05

Magno C


2 Answers

I’ve been working on this myself recently, and I wish I could say I have a simple answer, but I don’t. I would have to start by asking questions like, is this a web application (JSP etc) or a REST API used by a web application, or a REST API used by a mobile app, etc etc.

The reason this is important is that you first have to select one of the OAuth2 profiles and grant types, and they all have different requirements and configuration in Spring.

Also, are you trying to integrate with a third party OAuth2 authentication provider (e.g. Facebook) or is your application acting as both the authentication provider (where login and password validation occurs) and the protected resource (where the web page requests or API calls go to)?

So I guess the best I can do is assign you some homework:

(1) Read about the various OAuth2 profiles and determine which one best fits your application, and learn all the terminology (like, what is a client secret?).

This is definitely NOT one of those cases where you can just cut and paste example code without understanding it. If you don’t have a reasonable understanding of how OAuth2 works you are going to have a lot of difficulty.

Also: we’re talking about SECURITY here so doing stuff without understand it is a very bad idea. If you aren’t careful, you may think it’s working but in fact you’re leaving yourself wide open to attacks.

(2) if you are not familiar with Spring Framework Security you’ll need a basic grounding in that to understand what you’re doing.

(3) Once you have an idea which profile you’ll use, use that in a google search, e.g. “Spring oauth2 implicit grant” to find an example tailored for that profile.

There are a few out there and that’s a good place to start though I found I was not able to take any of the examples directly over to my application because of subtle differences in their assumptions and my application.

The Spring reference guide is helpful also but doesn’t necessarily give all the details for all the issues you may encounter. Finally, try to implement with your application.

You’ll want some good tools to send requests to your app (I like PostMan for that purpose) so you can inspect the data going back and forth. OAuth2 involves a complex series of HTTP redirects so testing can be a bit difficult.

Also, be patient. I consider myself a Spring expert and it still took me a few days to get things fully working the way I wanted. Note that there is actually VERY LITTLE code you end up writing, but getting the small amount of code exactly right is what’s difficult.

like image 57
2 revs, 2 users 93% Avatar answered Oct 22 '22 00:10

2 revs, 2 users 93%


Simple as 1,2,3 ...

Just change a little my OAuth2 server to accept oauth/authorize method.

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .requestMatchers()
        .antMatchers("/login", "/oauth/authorize")
    .and()
        .authorizeRequests()
        .anyRequest()
        .authenticated()
    .and()
        .formLogin()
        .permitAll();       
}

and create a custom login form. Now all clients (web applications) can login into it.

Here you can find a sample client and a more details: http://www.baeldung.com/sso-spring-security-oauth2

Also you can check my entire server and client at my github repo:

https://github.com/icemagno/geoinfra/cerberus

and

https://github.com/icemagno/geoinfra/atlas

It is in pt_BR

like image 30
Magno C Avatar answered Oct 21 '22 23:10

Magno C