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
accessTokenUri
Is the URI that gets the access tokenuserAuthorizationUri
Is the authorization URI to which the user will be redirected- The user terminal
userInfoUri
The 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…