Spring Boot OAuth2 SSO Example with AWS Cognito

Here in this example I am going to show you how to allow users for OAuth2 SSO (Single Sign On) using AWS (Amazon Web Services) Cognito. I had explained how to do OAuth2 Single Sign On using Spring Boot and GitHub account. Here I am going to use AWS Cognito. You can use any other providers, such as, Google, Facebook, etc.

SSO is where a user logs in with single set of credentials (username/password) to gain access to multiple software systems. OAuth is a protocol with which a 3rd-party app can access your data stored in another website without your account and password. For more information on OAuth 2, you can read https://oauth.net/2/.

Prerequisites

Java at least 8, Maven 3.6.3, AWS Cognito Configuration, Spring Boot 2.4.1, Thymeleaf, Spring OAuth2 Client

Configure AWS Cognito

First you need to login to AWS Console. You may also want to check whether you want to login as Root user or IAM user. In the next page you need to input password.

spring boot oauth2 sso with aws cognito

You need to select Cognito in the AWS management console:

spring boot oauth2 sso with aws cognito

You need to configure user in the AWS console. You can more information on this in the AWS Documentation.

You need to create user pool using Create a user pool option. Next you need to configure it to integrate this user pool with identity pool.

You need to create IAM role and add a specific access. Then you have to create user group and map it to new IAM role.

This Spring Boot application will act as a client therefore you need to add app client from the option General Settings -> App Client.

While configuring client app you need to give the App client name, Refresh token expiration (days), check the box Generate client secret, Enable lambda trigger based custom authentication (ALLOW_CUSTOM_AUTH), Enable SRP (secure remote password) protocol based authentication (ALLOW_USER_SRP_AUTH), Enable refresh token based authentication (ALLOW_REFRESH_TOKEN_AUTH). Then select the radio Enabled (Recommended). Finally click on Create app client.

Then you need to configure app client settings by going from the menu App Integration -> App Client Settings. The configuration should be something similar to the below image:

spring boot oauth2 sso with aws cognito

The callback and sing out URLs are important in the above configuration.

To use the sign up and login page hosted by AWS Cognito, you need to configure a domain name for it from the left side menu: App integration -> Domain Name.

spring boot oauth2 sso with aws cognito

Now I am moving to the Spring Boot application.

Project Setup

Create a maven based project in your favorite IDE or tool. The maven based build pom.xml file is given below with the required dependencies:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.roytuts</groupId>
	<artifactId>spring-oauth2-sso</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>12</maven.compiler.source>
		<maven.compiler.target>12</maven.compiler.target>
	</properties>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.1</version>
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</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-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-oauth2-client</artifactId>
		</dependency>
		<dependency>
			<groupId>org.thymeleaf.extras</groupId>
			<artifactId>thymeleaf-extras-springsecurity5</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

Application Configuration

Now I am going to configure AWS cognito as an identity provider for Spring application. The below application.yml/yaml file is kept under class path folder src/main/resources. Make sure you provide the appropriate configuration values for clientId, clientSecret, etc.

server:
  port: 8020

spring:
  security:
    oauth2:
      client:
        registration:
          cognito:
            clientId: <client id>
            clientSecret: <client secret>
            scope: openid, email
            authorization-grant-type: authorization_code
            redirect-uri: "{baseUrl}/login/oauth2/code/cognito"
            clientName: <client name>
        provider:
          cognito:
            user-info-uri: <user info URL>
            jwk-set-uri: <jwks URL>
            token-uri: <token URL>
            authorization-uri: <authorize URL>
            userNameAttribute: sub

Security Configuration

The Java based Spring security configuration class that permits access to base URL or root URL (“/”) and asks for authentication for any other URL.

The logout URL is configured in the AWS cognito configurations.

package com.roytuts.spring.oauth2.sso;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class OAuth2SsoSecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.csrf().and()
				.authorizeRequests(authorize -> authorize.mvcMatchers("/").permitAll().anyRequest().authenticated())
				.oauth2Login().and().logout().logoutUrl("/logout").logoutSuccessUrl("/");
	}

}

Controller

Spring controller class that displays the index.html page which uses Thymeleaf to represent the UI (User Interface). The controller is included in the main class that acts as a Spring boot application responsible for the deployment of the app in the embedded Tomcat server.

I am checking whether the user was authenticated or not and according I am adding to the model to show the authentication details on the UI.

package com.roytuts.spring.oauth2.sso;

import java.util.stream.Collectors;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
@SpringBootApplication
public class SpringOAuth2SsoApp {

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

	@GetMapping("/")
	public String home(Model model, Authentication authentication) {
		if (authentication != null && authentication.isAuthenticated()) {
			model.addAttribute("name", authentication.getName());
			model.addAttribute("principal", authentication.getPrincipal());
			model.addAttribute("authorities", authentication.getAuthorities().stream().map(a -> a.getAuthority())
					.collect(Collectors.joining(",")));
		}

		model.addAttribute("message", "AWS Cognito with Spring Security");

		return "index";
	}
}

View Template

This the Thymeleaf template file index.html which is kept under src/main/resources/templates folder.

This page shows the authentication details if user was authenticated successfully otherwise it shows login page.

<!DOCTYPE html>
<html lang="en"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
      xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="utf-8">
  <title>Spring Boot OAuth2 SSO Login AWS Cognito</title>
</head>
<body>
<div>
  <div>
    <h1 th:text="${message}"></h1>

    <div sec:authorize="isAuthenticated()">
      <p>Hello, <strong th:text="${#authentication.name}"></strong>!</p>
      <p>Your Authorities: <strong th:each="authority : ${#authentication.authorities}"><span
        th:text="${authority.authority} + ' '"></span></strong></p>
    </div>
    
    <div th:if="${message}">
      The message is: <strong th:text="${message}"></strong>
    </div>

    <div th:if="${name}">
      The name is: <strong th:text="${name}"></strong>
    </div>
    
    <!--<div th:if="${principal}" class="alert alert-primary" role="alert">
      The principal is: <strong th:text="${principal}"></strong>
    </div>-->
    
    <div th:if="${authorities}" class="alert alert-primary" role="alert">
      The authorities are: <strong th:text="${authorities}"></strong>
    </div>

    <div sec:authorize="isAnonymous()">
      <a th:href="@{/oauth2/authorization/cognito}">
        Login with AWS Cognito
      </a>
    </div>

    <div sec:authorize="isAuthenticated()">
      <form method="post" th:action="@{/logout}">
        <input type="submit" value="Logout"/>
      </form>
    </div>
  </div>
</div>
</body>
</html>

Testing the Application

Make sure you run the class having main method to deploy the application.

When you type URL http://localhost:8020, you will see the following login page:

spring boot oauth2 sso with aws cognito

Next clicking on Login with Amazon Cognito will redirect you to the following login page:

spring boot oauth2 sso with aws cognito

Now you can use your gmail login credentials to authenticate the account or you can use login credentials for your open id to authenticate your account. I used my gmail id by clicking on Sign in with Google to authenticate the system.

Once you are success fully authenticated you will be redirected to the home page with the following output:

spring boot oauth2 sso with aws cognito

That’s all about OAuth2 SSO example with Amazon Cognito.

You can improve the application in the following areas:

  • You can completely remove the custom login page and it will directly take you to the OAuth2 login page
  • You can register multiple clients and based on each client the appropriate OAuth2 login page will be shown
  • You can also redirect to different page after successful authentication

Need Help? Send an email to roytuts2014@gmail.com or using About page.

Source Code

Download

Leave a Reply

Your email address will not be published. Required fields are marked *