www.baeldung.com/sso-spring-…

Author: baeldung

From stackGC

1, an overview of the

In this tutorial, we will discuss how to implement SSO (single sign-on) using Spring Security OAuth and Spring Boot.

This example uses three separate applications

  • An authorization server (Central Authentication Mechanism)
  • Two client applications (using SSO)

In short, when a user tries to access a secure page of a client application, they first authenticate through an authentication server redirect.

We will use the Authorization Code Authorization type in OAuth2 to drive Authorization.

2. Client applications

Start with the client application and use Spring Boot to minimize the configuration:

2.1 Maven dependency

First, you need to add the following dependencies to pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
Copy the code

2.2. Security Configuration

Next, the most important part is the security configuration of the client application:

@Configuration
@EnableOAuth2Sso
public class UiSecurityConfig extends WebSecurityConfigurerAdapter {
     
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/ * *")
          .authorizeRequests()
          .antMatchers("/"."/login**") .permitAll() .anyRequest() .authenticated(); }}Copy the code

Of course, the core part of this configuration is the @enableoAuth2SSO annotation, which we use to enable single sign-on.

Please note that we need to inherit WebSecurityConfigurerAdapter – without it, all the paths will be protected, so the user trying to access any page will be redirected to the login page. In the current example, the index page and the login page can be accessed without authentication.

Finally, we also define a RequestContextListener bean to process the request.

Application. Yml:

server:
    port: 8082
    context-path: /ui
    session:
      cookie:
        name: UISESSION
security:
  basic:
    enabled: false
  oauth2:
    client:
      clientId: SampleClientId
      clientSecret: secret
      accessTokenUri: http://localhost:8081/auth/oauth/token
      userAuthorizationUri: http://localhost:8081/auth/oauth/authorize
    resource:
      userInfoUri: http://localhost:8081/auth/user/me
spring:
  thymeleaf:
    cache: false
Copy the code

A few caveats:

  • We disabled the default Basic Authentication
  • accessTokenUriIs the URI that gets the access token
  • userAuthorizationUriIs the authorization URI to which the user will be redirected
  • The user terminaluserInfoUriThe URI is used to obtain detailed information about the current user

Also note that in this example, we used our own authorization server, although we could have used another third-party provider, such as Facebook or GitHub.

2.3, the front-end

Now let’s look at the front-end configuration of the client application. We don’t want to spend too much time here, mainly because we’ve covered it before.

The client application has a very simple front end:

Index.html:

<h1>Spring Security SSO</h1>
<a href="securedPage">Login</a>
Copy the code

SecuredPage. HTML:

<h1>Secured Page</h1>
Welcome, <span th:text="${#authentication.name}">Name</span>
Copy the code

Securedpage.html pages require user authentication. If an unauthenticated user tries to access securedPage.html, they will be redirected to the login page first.

3. Authentication server

Now let’s start talking about authorization servers.

3.1 Maven dependency

First, define the dependencies in POM.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
</dependency>
Copy the code

3.2 OAuth configuration

It is important to understand why we run the authorization server and resource server together as a single deployable unit here.

Let’s start with configuring the resource server:

@SpringBootApplication
@EnableResourceServer
public class AuthorizationServerApplication extends SpringBootServletInitializer {
    public static void main(String[] args) { SpringApplication.run(AuthorizationServerApplication.class, args); }}Copy the code

After configuring the authorization server:

@Configuration
@EnableAuthorizationServer
public class AuthServerConfig 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("secret")
          .authorizedGrantTypes("authorization_code")
          .scopes("user_info")
          .autoApprove(true); }@Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager); }}Copy the code

Note that we use the authorization_code authorization type to start a simple client.

3.3. Security Configuration

First, we’ll disable the default Basic Authentication via application.properties:

server.port=8081
server.context-path=/auth
security.basic.enabled=false
Copy the code

Now, let’s go to the configuration and define a simple form login mechanism:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Autowired
    private AuthenticationManager authenticationManager;
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatchers()
          .antMatchers("/login"."/oauth/authorize")
          .and()
          .authorizeRequests()
          .anyRequest().authenticated()
          .and()
          .formLogin().permitAll();
    }
 
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.parentAuthenticationManager(authenticationManager)
          .inMemoryAuthentication()
          .withUser("john").password("123").roles("USER"); }}Copy the code

Note that although we used simple in-memory authentication, it can easily be replaced with a custom userDetailsService.

3.4. User endpoints

Finally, we will create the user endpoint that was previously used in the configuration:

@RestController
public class UserController {
    @GetMapping("/user/me")
    public Principal user(Principal principal) {
        returnprincipal; }}Copy the code

The user data will be returned as JSON.

4, the conclusion

In this quick tutorial, we implemented single sign-on using Spring Security Oauth2 and Spring Boot.

As always, you can find the full source code on GitHub.

Original project sample code

Github.com/eugenp/tuto…