Integrate your Spring Boot app¶
This page guides you through integrating your spring-boot application with WSO2 Identity Server for secure authentication using OpenID Connect standard.
Tip
If you want to try out an existing sample, see Run Spring-boot sample.
Register application¶
To register your application as a service provider in the WSO2 Identity Server:
-
Log in to the WSO2 Identity Server Management Console using administrator credentials.
-
Go to Main > Identity > Service Providers > Add.
-
Enter a Service Provider Name. Optionally, enter a Description.
-
Click Register.
-
Expand Inbound Authentication Configuration.
-
Expand OAuth/OpenID Connect Configuration and click Configure.
-
Enter
http://localhost:8080/spring-boot-sample/login/oauth2/code/wso2
as the Callback Url.Tip
The Callback Url is the exact location of the service provider's application to which the authorization code should be sent. This should always be
{baseUrl}/login/oauth2/code/wso2
. -
Select Enable OIDC Backchannel Logout if you wish to configure a logout URL.
-
Enter
http://localhost:8080/spring-boot-app/login
as the Backchannel Logout Url. -
Select Add.
-
Note the Client ID and Client Secret that appear.
Field Value Sample Value Service Provider Name your-application-name sample-app Description This is a spring-boot application This is a spring-boot application CallBack Url http://localhost:8080/spring-boot-app/login/oauth2/code/wso2 Logout Url http://localhost:8080/spring-boot-app/login
Add the dependency¶
Add the following dependencies to the pom file in the spring-boot-project.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
Add configurations¶
Add the following configurations related to WSO2 Identity Server and the application in order to make the authentication process secure.
-
Create the
application.yml
file in thesrc/main/resources
folder. -
Copy the following configurations.
Configuration
provider: host: <is-host-name> #Change the host spring: security: oauth2: client: registration: wso2: client-name : WSO2 Identity Server client-id: <application-client-id> #Change client-id client-secret: <application-client-secret> # Change client-secret authorization-grant-type: authorization_code scope: openid provider: wso2: issuer-uri: ${provider.host}/oauth2/oidcdiscovery thymeleaf: cache: false
Example
provider: host: https://localhost:9443 #Change the host spring: security: oauth2: client: registration: wso2: client-name : WSO2 Identity Server client-id: LQTLEgDFil5Tyf0wS5KWUShkMDEa #Change client-id client-secret: uFwLrbBKhp74NWT1zBIjXuXuYUa # Change client-secret authorization-grant-type: authorization_code scope: openid provider: wso2: issuer-uri: ${provider.host}/oauth2/oidcdiscovery thymeleaf: cache: false
Login¶
Use the default /login
endpoint¶
-
Spring Boot generates a default login page. All the endpoints of the application are secured except the
/login
page. -
If you try to access any page of your application, it will redirect to WSO2 Identity Server login page since all the pages are secured.
-
If the
/login
endpoint is accessed, it redirects to the default login page of the spring-boot application.
Remove the default “/login” page and redirect directly to the WSO2 IS login page¶
-
Create a
ConfigSecurity
class and extendWebSecurityConfigurerAdapter
.@EnableWebSecurity public class ConfigSecurity extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/login") .permitAll() .anyRequest() .authenticated() .and() .oauth2Login().loginPage("/login"); } }
-
When the application tries to call the
/login
endpoint, add redirection to"/oauth2/authorization/wso2"
in the Controller. This will skip the login page.@GetMapping("/login") public String getLoginPage(Model model) { return "redirect:/oauth2/authorization/wso2"; }
Customize the login page and use another login endpoint¶
Even though Spring Boot generates a default login page, follow the instructions given below to customize the page as required.
-
Add a
ConfigSecurity
class by extendingWebSecurityConfigurerAdapter
.import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @EnableWebSecurity public class ConfigSecurity extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/oidc-login") .permitAll() .anyRequest() .authenticated() .and() .oauth2Login().loginPage("/oidc-login"); } }
-
Create a
LoginController
class and render the login page when the browser is redirected to/oauth-login
.@Controller public class LoginController { private static String authorizationRequestBaseUri = "oauth2/authorization"; Map<String, String> oauth2AuthenticationUrls = new HashMap<>(); @Autowired private ClientRegistrationRepository clientRegistrationRepository; @GetMapping("/oidc-login") public String getLoginPage(Model model) { Iterable<ClientRegistration> clientRegistrations = null; ResolvableType type = ResolvableType.forInstance(clientRegistrationRepository) .as(Iterable.class); if (type != ResolvableType.NONE && ClientRegistration.class.isAssignableFrom(type.resolveGenerics()[0])) { clientRegistrations = (Iterable<ClientRegistration>) clientRegistrationRepository; } clientRegistrations.forEach(registration -> oauth2AuthenticationUrls.put(registration.getClientName(), authorizationRequestBaseUri + "/" + registration.getRegistrationId())); model.addAttribute("urls", oauth2AuthenticationUrls); return "oidc-login"; } }
-
Create a template at
src/main/resources/templates/oidc-login.html
to display the login option.<!DOCTYPE html> <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>Login with:</h3> <p th:each="url : ${urls}"> <a th:text="${url.key}" th:href="${url.value}">Client</a> </p> </body> </html>
Logout¶
Use the default/logout endpoint¶
By default, Spring Boot provides the /logout
endpoint to provide the logout capability.
Follow the instructions given below to configure the post logout URI.
-
Configure a
ConfigSecurity
class by extendingWebSecurityConfigurerAdapter
.@EnableWebSecurity public class ConfigSecurity extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/login") .permitAll() .anyRequest() .authenticated() .oauth2Login() .loginPage("/login") .and() .logout() .logoutSuccessHandler(oidcLogoutSuccessHandler()); } @Autowired private ClientRegistrationRepository clientRegistrationRepository; private LogoutSuccessHandler oidcLogoutSuccessHandler() { OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler = new OidcClientInitiatedLogoutSuccessHandler( this.clientRegistrationRepository); oidcLogoutSuccessHandler.setPostLogoutRedirectUri( URI.create("http://localhost:8080/oauth-login")); //Need to give the post-rediret-uri here return oidcLogoutSuccessHandler; } }
-
Create a template at
src/main/resources/login.html
to display the logout option and have a logout button. -
Add the
/logout
redirection when user clicks the Logout button.<div style="float:right"> <form method="post" th:action="@{/logout}" class="navbar-form navbar-right"> <button id="logout-button" type="submit" class="btn btn-danger">Logout</button> </form> </div>
Customize the logout endpoint¶
To customize the logout endpoint, create a ConfigSecurity
class by extending WebSecurityConfigurerAdapter
, and configure the logoutUrl
.
@EnableWebSecurity
public class ConfigSecurity extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login")
.permitAll()
.anyRequest()
.authenticated()
.and().oauth2Login().loginPage("/login")
.and().logout().logoutUrl("/applogout)
.logoutSuccessHandler(oidcLogoutSuccessHandler());
}
@Autowired
private ClientRegistrationRepository clientRegistrationRepository;
private LogoutSuccessHandler oidcLogoutSuccessHandler() {
OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler =
new OidcClientInitiatedLogoutSuccessHandler(
this.clientRegistrationRepository);
oidcLogoutSuccessHandler.setPostLogoutRedirectUri(
URI.create("http://localhost:8080/spring-boot-app"));
return oidcLogoutSuccessHandler;
}
}
Have a Logout button and redirect to custom logout (“/applogout”) url¶
-
Create a template at
src/main/resources/login.html
to display the Logout option and have a logout button. -
Add the
/applogout
redirection when user clicks theLogout
button.<div style="float:right"> <form method="post" th:action="@{/applogout}" class="navbar-form navbar-right"> <button id="logout-button" type="submit" class="btn btn-danger">Logout</button> </form> </div>
Read user information¶
You can get the user information from org.springframework.security.core.Authentication
and org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser
classes.
-
Add a method to handle redirection to the
/userinfo
endpoint. Add a method in your controller class to get information from the id token.@GetMapping("/userinfo") public String getUser(Authentication authentication, Model model) { model.addAttribute("userName", userName); model.addAttribute("idtoken", user.getClaims()); LOGGER.log(Level.INFO, "UserName : " + userName); LOGGER.log(Level.INFO, "User Attributes: " + user.getClaims()); return "userinfo"; }
-
Create another template
userinfo.html
atsrc/main/resources/templates
to display the idtoken claims.<div> <table class="details"> <tr th:each="instance : ${idtoken}"> <td style="text-align:left;width:100px" th:text="${instance.key}">keyvalue</td> <td style="text-align:left" th:text="${instance.value}">num</td> </tr> </table> </div>