Java – Spring Security – Implement oauth2 SSO

Spring Security – Implement oauth2 SSO… here is a solution to the problem.

Spring Security – Implement oauth2 SSO

I want to implement a central authentication system with Spring Security and OAuth2 SSO. In other words, I have a Spring Boot application responsible for authorization and a simple client. My customer has a rest API. First, I get the token from the authorization server and then send a request to the client API where the authorization header contains the bearer token from the above request. But this request always logs me in to the page.

Here is the server-side and client-side implementation:

Server

AuthorizationServerConfig.java

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

@Autowired
private AuthenticationManager authenticationManager;

@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    oauthServer
            .tokenKeyAccess("permitAll()")
            .checkTokenAccess("isAuthenticated()");
}

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients.inMemory()
            .withClient("SampleClientId")
            .secret("{noop}secret")
            .authorizedGrantTypes("password")
            .scopes("user_info")
            .autoApprove(true);
}

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

App configuration:

@SpringBootApplication
@EnableResourceServer
public class ApplicationConfig extends SpringBootServletInitializer {

public static void main(String[] args) {
    SpringApplication.run(ApplicationConfig.class, args);
}

}

Security configuration:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    this is just example
    auth.inMemoryAuthentication().withUser("user").password("{noop}1234").roles("user");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.requestMatchers()
            .antMatchers("/login", "/oauth/authorize", "/oauth/token")
            .and()
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .formLogin().permitAll();

}

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

application.yml:

server:
  port: 8900
  servlet:
    context-path: /auth

Client:

App configuration:

@SpringBootApplication
public class ApplicationConfig {

public static void main(String[] args) {
    SpringApplication.run(ApplicationConfig.class, args);
}

}

Security configuration:

@Configuration
@EnableOAuth2Sso
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {

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

Test Controller:

@RestController
public class HomeController {

@GetMapping("/")
public String index() {
    return "home";
}

@RequestMapping("/admin")
public String admin() {
    return "admin";
}
}

application.yml:

server:
  port: 9000
  servlet:
    context-path: /client1
security:
  basic:
    enabled: false
  oauth2:
    client:
      clientId: SampleClientId
      clientSecret: secret
      accessTokenUri: http://localhost:8900/auth/oauth/token
      userAuthorizationUri: http://localhost:8900/auth/oauth/authorize
    resource:
      userInfoUri: http://localhost:8900/auth/user/me

First, I sent the client_id and password along with the username, password, and grant_type to localhost:8900/auth/oauth/token and got the following result:

{
  "access_token": "603b505f-e701-43d0-b8b8-976a2178f7ea",
  "token_type": "bearer",
  "expires_in": 43199,
  "scope": "user_info"
}

Now, I get the token above and send a request to localhost:9000/client1/admin
header contains the above tags. But the client application seems to ignore the header and display the server login page as a result. How do I fix this?

Solution

@EnableOAuth2Sso is a comment that uses OAuth 2.0 as an end-user authentication mechanism (for example, a “A Login with Google” button). This annotation connects your app to a login page that redirects to the authorization server, where you will sign in and then redirect back to your app.

If this is your intention, then you need to update your Authorization Server to Support the authorization_code grant flow instead of the password authorization process.

However, if your client is strictly a REST API, you are more likely to need to connect to the client using @EnableResourceServer rather than @EnableOAuth2Sso. A Resource Server authorizes tokens through the Authorization HTTP header.

Related Problems and Solutions