Skip to content

Protect Service with Spring Security and OAuth2

Wuyi Chen edited this page Jul 3, 2019 · 31 revisions

Overview

For protecting your services with Spring Security and OAuth2, you need to do several things


Configure the authentication service

Set dependencies

build.gradle

dependencies {
    // Spring Security and OAuth2
    compile group: 'org.springframework.cloud',          name: 'spring-cloud-security'
    compile group: 'org.springframework.security.oauth', name: 'spring-security-oauth2',       version: '2.1.3.RELEASE'

    // For storing credentials and roles in database
    compile group: 'org.springframework.boot',           name: 'spring-boot-starter-data-jpa', version: '1.5.0.RELEASE'
    compile group: 'org.springframework.boot',           name: 'spring-boot-autoconfigure',    version: '1.5.0.RELEASE'
    compile group: 'mysql',                              name: 'mysql-connector-java',         version: '5.1.38'
}

Change the application configuration

After Spring Boot 1.5, the order of the OAuth2 resource filter has been changed. So you need to restore it to the original default value. Otherwise when you hit the URL: http://localhost:8901/auth/user to retrieve the user information, it will return a login page rather than the user information in JSON.

application.yml

security:
  oauth2: 
    resource:
      filter-order: 3

Set the client application's credential

For storing client application's credential, it can be stored in

Store in memory

OAuth2Config.java

@Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {            // Define what client applications are registered with the service
        clients.inMemory()                                                                      // Store the application information in memory
                .withClient("eagleeye")                                                         // Specify which client application will register
                .secret("thisissecret")                                                         // Specify the secret which will be used to get the access token
                .authorizedGrantTypes("refresh_token", "password", "client_credentials")        // Provide a list of the authorization grant types that will be supported by the service
                .scopes("webclient", "mobileclient");                                           // Define the types of the client applications can get the access token from the service
    }

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

Store in database

See Store Clients and Users' Credentials to DB


Set the client users' credentials and roles

For storing client users' credentials and roles, it can be stored in

Store in memory

WebSecurityConfigurer.java

@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    @Bean
    public UserDetailsService userDetailsServiceBean() throws Exception {
        return super.userDetailsServiceBean();
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()
                .withUser("john.carnell").password("password1").roles("USER")                 // Define the first user: john.carnell with the password "password1" and the role "USER"
                .and()
                .withUser("william.woodward").password("password2").roles("USER", "ADMIN");   // Define the second user: william.woodward with the password "password2" and the role "ADMIN"
    }
}

Store in database

See Store Clients and Users' Credentials to DB

Store in LDAP server

(Need to do)


Generate the access token

We will hit the endpoint of the authentication service to get the access token.

  • URL: http://localhost:8901/auth/oauth/token

  • Method: POST

  • Authentication

    • Type: Basic Auth
    • Username: eagleeye
    • Password: thisissecret
  • Body:

    Key Value
    grant_type password
    scope webclient
    username john.carnell
    password password1

After sending the HTTP request to the authentication service with the credential, it will return the access token:

{
    "access_token": "945ab1d3-beec-4e57-839b-bee7ef2cb167",
    "token_type": "bearer",
    "refresh_token": "fca36d96-debb-430d-a7d1-adcffe512034",
    "expires_in": 43199,
    "scope": "webclient"
}

The value 945ab1d3-beec-4e57-839b-bee7ef2cb167 is the access token.


Configure the protected service

In this example, we will use the organization service as a protected service.

Set dependencies

build.gradle

dependencies {
    // Spring Security and OAuth2
    compile group: 'org.springframework.cloud',          name: 'spring-cloud-security'
    compile group: 'org.springframework.security.oauth', name: 'spring-security-oauth2',       version: '2.1.3.RELEASE'
}

Change the application configuration

You need to let the protected service know where is the authentication service which can validate the OAuth2 access token.

application.yml

security:
  oauth2:
    resource:
      userInfoUri: http://localhost:8901/auth/user     # This is the URL to validate the access token

Add the annotation to the bootstrap class

Application.java

@EnableResourceServer                           // Enable this service as the protected resource by OAuth2
public class Application {
	public static void main(String[] args) {
	    SpringApplication.run(Application.class, args);
	}
}

Define permissions

You can give permissions to:

Give permissions to all authenticated users

ResourceServerConfiguration.java

@Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception{
        http
                .authorizeRequests()
                .anyRequest()
                .authenticated();
    }
}

Give permissions to a group of users with a certain role

ResourceServerConfiguration.java

@Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception{
        http
                .authorizeRequests()
                .antMatchers(HttpMethod.DELETE, "/v1/organizations/**")
                .hasRole("ADMIN")                                        // Only ADMIN role have the permission to do DELETE operations
                .anyRequest()
                .authenticated();
    }
}

Verify: Send the HTTP request to the protected service with the access token

After setting up the protected service, when you sent a HTTP request to that protected service, the header of the request should contain the access token.

Key Value
Authorization Bearer 945ab1d3-beec-4e57-839b-bee7ef2cb167

(You may need to get a new access token for your case)


References

Clone this wiki locally