OAuth 2.0, AWS Cognito, Spring Boot, Spring Security, Java

AWS Cognito - Extract groups in a Spring Boot application

A tutorial about how to extract user groups configured in AWS Cognito in a Spring Boot application

Author Martin
Martin22nd March 2021

In this tutorial, we will show you, how you can extract the groups of an AWS Cognito user in your Spring Boot application. The OAuth token from AWS Cognito provider encodes the user groups in a field called "cognito:groups". The following example shows you how you can map these groups to Spring Security roles.

Example

This example is a Spring Security configuration that maps the AWS Cognito groups of the logged in user to Spring Security authorities.

1@EnableWebSecurity
2public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
3
4    @Override
5    protected void configure(final HttpSecurity http) throws Exception {
6        http
7                .authorizeRequests(a -> a
8                        .anyRequest().authenticated()
9                )
10                .oauth2Login(l -> {
11                            l.userInfoEndpoint().userAuthoritiesMapper(userAuthoritiesMapper());
12                        }
13                );
14    }
15
16    @Bean
17    public GrantedAuthoritiesMapper userAuthoritiesMapper() {
18        return (authorities) -> {
19            Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
20
21            Optional<OidcUserAuthority> awsAuthority = (Optional<OidcUserAuthority>) authorities.stream()
22                    .filter(grantedAuthority -> "ROLE_USER".equals(grantedAuthority.getAuthority()))
23                    .findFirst();
24
25            if (awsAuthority.isPresent()) {
26                mappedAuthorities = ((JSONArray) awsAuthority.get().getAttributes().get("cognito:groups")).stream()
27                        .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
28                        .collect(Collectors.toSet());
29            }
30
31            return mappedAuthorities;
32        };
33    }
34}

The authority with the name "USER_ROLE" is the OpenID Connect Token, which holds all the information about the user provided by AWS Cognito. Once we have the OpenID token we extract the AWS Cognito groups from the property "cognito:groups". The value is a JSONArray that holds all groups of the user. We can now extract these groups and map them to SimpleGrantedAuthority roles, which Spring Security understands.

Annotating controllers with Spring Security annotations

Now that we have mapped our AWS Cognito groups into a format that our Spring Security context can understand, we can annotate our controllers with the well known Spring Security annotations.

1@RestController
2public class CommentController {
3
4  @PreAuthorize("hasRole('COMMENTER')")
5  @GetMapping("/comments")
6  public String getComments() {
7    return "comments";
8  }
9
10  @PreAuthorize("hasRole('MODERATOR')")
11  @DELETE("/comments")
12  public void deleteComments() {
13    // delete comments
14  }
15}

Conclusion

We can easily map the groups from the AWS Cognito user to Spring Security authorities with just a few lines of code and then make use of the large ecosystem provided by Spring to secure our application.