Skip to content

Latest commit

 

History

History
369 lines (272 loc) · 10.7 KB

HowToIntegrateWithSpringBoot.md

File metadata and controls

369 lines (272 loc) · 10.7 KB

Integrate your Spring-boot application with WSO2 Identity Server

Overview

This showcases the capability to integrate your spring-boot application with WSO2 Identity Server for secure authentication using OpenID Connect standard.

Register Application

Register an OIDC application as mentioned in the README

Add the dependency

Add the following dependencies in the pom file in your 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>

Configurations

Need to add configurations related WSO2 to Identity Server and application in order to make secure authnetication.

Create a application.yml file inside src/main/resources folder.

Copy the following configurations.

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/token

  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/token

  thymeleaf:
    cache: false

Login

Use the Default “/login” endpoint

  • Spring Boot generates a default login page for us. All the endpoint of the application is secured except this /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 you go to “/login” endpoint, you can get the default login page of the spring-boot-security.

Remove the default “/login” page and redirect directly to IS login page.

  1. Create a ConfigSecurity class and Extend the WebSecurityConfigurerAdapter.
@EnableWebSecurity
public class ConfigSecurity extends WebSecurityConfigurerAdapter {

   protected void configure(HttpSecurity http) throws Exception {

       http.authorizeRequests()
               .antMatchers("/login")
               .permitAll()
               .anyRequest()
               .authenticated()
               .and()
               .oauth2Login().loginPage("/login");
   }
}
  1. When the application tries to call /login endpoint, add redirection to "/oauth2/authorization/wso2" in your Controller. Then that would skip the login page.
@GetMapping("/login")
public String getLoginPage(Model model) {

   return "redirect:/oauth2/authorization/wso2";
}

Customizing the login page and uses another login endpoint

  • Even Though SpringBoot generates a default login page for us, we'll usually want to define our own customized page.
  1. Add a ConfigSecurity class by extending WebSecurityConfigurerAdapter
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");
   }
}
  1. Have a Login Controller Class and render your 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";
   }
}

Have a oidc-login.html page inside resources/templates folder

Create a template at src/main/resources/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 /logout endpoint to provide logout capability. You can use that default endpoint.

Also you need to have a postlogout uri configured.

  1. Have a ConfigSecurity class by extending WebSecurityConfigurerAdapter
@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;
   }
}
  1. 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>

Customizing the logout endpoint

If you wish to customize the logout endpoint, follow the steps below.

  1. Have 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

  1. 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 the Logout 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, org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser class.
  1. Add a method to handle redirection to /userinfo endpoint. Add a method in your controller class to get information from 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";
   }
  1. Create another template userinfo.html at src/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>