Skip to main content

Command Palette

Search for a command to run...

How to secure Spring boot REST API endpoints with Amazon Cognito

Published
4 min read
How to secure Spring boot REST API endpoints with Amazon Cognito
W

Hello, I am a full stack developer since 2010 focused for a long moment more on backend stuffs. I embraced cloud development since 2019.

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, and 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 the 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/
  • 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.

H

Hi Wilson, Thanks for the very informative article. I followed your blog step by step up until the point where I need to sign up/sign in to generate a token via postman.

The auth URL in your screenshot looks like: https://<clientId>.auth.<aws-region>/login but when I use my clientId and aws-region, it doesnt work.

Am I missing something?

Also is the auth URL same as domain because my domain looks like: https://<app-name>.auth.<aws-region>

1
W

Hi Hari,

Glad you read the post. The auth URL is :<< https://<clientId>.auth.<aws-region>.amazoncognito.com/login >>, don't forget ".amazoncognito.com" before /login , not << https://<clientId>.auth.<aws-region>/login >>.

Hope this will help you.

H

Wilson KOMLAN Hi Wilson, Just to give an update, I used the auth URL in the format you mentioned: << https://<clientId>.auth.<aws-region>.amazoncognito.com/login >>

but I still couldn't get it to work. I was able to sign in, was redirected to the callback URI with an auth code on browser but postman kept complaining invalid_client and was never able to fetch a token.

So I created a new app client with a client secret, used that to signin and get an auth code from the /login endpoint.

I then manually called the oauth2/token endpoint in a new tab via postman using this auth code and bunch of other attributes as mentioned in the below guide: https://medium.com/vedity/aws-cognito-token-generation-for-rest-api-calls-d32ce909894c and managed to generate the token. I was then able to use the token to call my spring boot API.

So instead of doing it in 1 step, I ended up doing 2 steps but I am mighty pleased that my API is secure with AWS cognito, all thanks to you.

I am now planning to try out your Spring boot API + AWS Fargate guide.

Thanks a lot mate! God bless you!

1

More from this blog

W

Wilson KOMLAN's blog page

14 posts

Hello, I am a freelance full stack developer.