DEV Community

Cover image for How to secure Spring boot REST API endpoints with Amazon Cognito
Wilson K. KOMLAN for AWS Community Builders

Posted on • Updated on • Originally published at wilkom2009.hashnode.dev

How to secure Spring boot REST API endpoints with Amazon Cognito

Hello! For Java backend developers, with Spring security there are many ways to secure Spring boot Rest APIs.

Usually, implementing Spring boot bearer token functionality for Rest API requires many lines of code, hours, and the need for user management. However, using Spring boot AWS authentication thanks to Amazon Cognito, things become very simple and very very fast. We no longer need to manage users, Amazon Cognito user pool takes care of that. Cognito also allows us to share users between many Rest APIs and front-ends (web, mobile).

Create Amazon Cognito User Pool

  1. Sign in into Amazon console, and then search for : Cognito.
    Amazon Cognito page

  2. Click on Create User Pool.

  3. In the Configure sign-in experience step, check User name, Email and Allow users to sign in with a preferred user name options then click on Next.

  4. In the Configure security requirements step, leave all the default options except MFA enforcement where you should choose No MFA instead of Require MFA - Recommended, then click on Next.

  5. Step 3 : Configure sign-up experience, leave all default options and click on Next.

  6. Step 4: Configure message delivery, choose Send email with Cognito for Email provider and leave all other default options then click on Next.

  7. Step 5: Integrate your app, provide the User pool name : Demo-user-pool, App client name: Dockerdemo-app, leave other default options and click Next.

  8. Step 6: Review and click on Create User Pool.
    Amazon cognito Demo user pool

  9. In the details page of the created user pool, click on App Integration tab -> Actions -> Create Cognito Domain and provide the domain name then click Create Cognito Domain.

  10. Again, in the App Integration tab, navigate to the App client list section and click on Dockerdemo-app to preview its details.
    Amazon cognito app client details

  11. In the App client details, scroll down to the Pinpoint analytics section and click on Edit, the Edit Hosted UI page will open.

  12. In the Edit Hosted UI page, provide the Allowed callback URLs : https://example.com, check Cognito user pool in the Identity providers section, check all OpenID Connect scopes options then click Save changes.

  13. Back to the App client details, the Pinpoint analytics section should look like the image below:
    Amazon cognito App client hosted UI

  14. Make sure to save the Cognito domain from the Domain section, and the Client ID for the created client App from the App client list section.

Create Spring boot Rest API

In this section, we will create a spring boot Rest API. For demonstration purposes, you can clone the Git hub repository here and open it in your favorite IDE.
The idea here is to implement Spring security Rest API authentication with OAuth 2.0 JWT Bearer Tokens.
Instead of implementing the JWT authentication tokens generation mechanism, we will use Amazon Cognito to manage it.

  1. Provide the needed dependencies in the pom.xml file for Spring security OAuth 2.0 support

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
    <dependency>             
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource- 
    server</artifactId>
    </dependency>
    
  2. In the application.yaml file, specify the Authorization Server:

    spring:
      security:
        oauth2:
          resourceserver:
            jwt:
              issuer-uri: https://cognito-idp.[AWS REGION].amazonaws.com/[USER_POOL_ID]
    
  3. Create a security configuration file.

    package com.wilkom.dockerdemo.security;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.web.SecurityFilterChain;
    
    @EnableWebSecurity // Enable Spring Security’s web 
      security support
    @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) // To configure method-level security
    public class SecurityConfig {
    
        @Bean
        public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    
            http.cors().and().csrf().disable()
                .authorizeRequests(expressionInterceptUrlRegistry -> expressionInterceptUrlRegistry
                        .anyRequest().authenticated())
                .oauth2ResourceServer().jwt();
            return http.build();
        }
    }
    

In the configuration class above, we have made each endpoint accessible only by OAuth 2.0 authenticated requests. That's all we have to do in our API Rest backend.

Test the Rest API

We will use Postman to test our Rest API.

1. Signup user into the Amazon Cognito

  • Open Postman and provide values from Amazon Cognito User provider settings: Postman Authorization Token generation

2/ Callback URL : https://example.com (make sure to provide the exact callback url you set in the Cognito)
3/ Auth URL : https://xxxxx.auth.us-east-1.amazoncognito.com/login (remember to append /login)
4/ Access Token URL : https://xxxxx.auth.us-east-1.amazoncognito.com/oauth2/token (remember to append /oauth2/token)
5/ Client ID : Dockerdemo-app App Client ID

  • Then click on Get New Access Token at the bottom, the Sign-in screen will open, click on Sign up link at the bottom the get the signup screen as follow:
    Cognito Sign up screen

    Enter user name, valid email and password then click on Sign-up.

  • The verification code screen should appear, open the valid email box to get the verification code:
    Cognito verification code screen

  • If the code verification is successful, a token will be generated, click on Use Token:
    Postman token generated

2. Make API call

  • Now, you can run the Spring boot app.

  • Go to Postman, enter a GET endpoint URL,

localhost:8080/api/
Enter fullscreen mode Exit fullscreen mode
  • Make sure the token is in use in the Authorization OAuth 2.0 tab and click on Send:

Postman Get request successful

PS : In a real project, the Signup and Sign-in processes will be implemented in the front-end apps, please see this guide to do so.

As you can see, Amazon Cognito is an amazing AWS service that simplifies Spring boot backend Rest API user management.

Thanks for reading.

Discussion (1)

Collapse
shebinhere profile image
Shebin • Edited on

Thanks for this. Much appreciated.

I have a question though. How to know which user is accessing the API from the JWT token? I can see there is a field named "username" in the JWT body. Should I rely on that to map the authenticated user to the DB I have? Also how can I support roles and granted authorities?