Amazon Cognito Oauth2 with Spring Security

我正在尝试使用“Cognito Oauth2”在资源服务器中实现Spring Security,但是我似乎没有找到太多信息。关于它(或者如果有可能这样做)。

我最近的方法是使用“Nimbus+JOSE”来检查“访问令牌”与“JWKS”的有效性,并授予访问资源的权限。(类似于他们给出的“API网关资源保护实现”的例子,https://aws.amazon.com/es/blogs/mobile/integrating-amazon-cognito-user-pools-with-api-gateway/)


答案 1

使用最新的Sprint Boot 2.x / Sprint Security 5.x的Oauth2的一个很好的起点可以在这里找到:https://spring.io/blog/2018/03/06/using-spring-security-5-to-integrate-with-oauth-2-secured-services-such-as-facebook-and-github

它使用Facebook / Github作为示例,但您也可以将其应用于AWS Cognito。

这是迄今为止使用Spring Security / Cognito OAuth2设置安全REST后端的最简单方法。您的后端将通过Spring Security进行保护,AWS Cognito将用作身份提供商。

您可以使用本文中概述的弹簧安全启动器设置香草弹簧启动应用,并使用以下依赖项:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-oauth2-client</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-oauth2-jose</artifactId>
    </dependency>

并提供您的认知配置(客户端注册+提供者定义),如下所示:

spring:
  security:
    oauth2:
      client:
        registration:
          cognito-client-1:
            client-id: 391uhnjlr8v8kicm3cru6g1s8g
            client-secret: xxxxxxxxxxxxxxxxxxxxxxxxxx
            client-name: Cognito Code Grant
            provider: cognito
            scope: openid
            redirect-uri-template: http://localhost:8080/login/oauth2/code/cognito
            authorization-grant-type: authorization_code
        provider:
          cognito:
            authorization-uri: https://custom-domain.auth.eu-central-1.amazoncognito.com/oauth2/authorize
            token-uri: https://custom-domain.auth.eu-central-1.amazoncognito.com/oauth2/token
            user-info-uri: https://custom-domain.auth.eu-central-1.amazoncognito.com/oauth2/userInfo
            jwk-set-uri: https://cognito-idp.eu-central-1.amazonaws.com/eu-central-1_xxxxxxxxx/.well-known/jwks.json
            user-name-attribute: cognito:username

就Cognito而言,您需要有一个用户池/身份池,其中包含几个用户和一个有效的应用程序客户端(=在spring配置中)在cognito中client-id

  • 一个秘密( = 在弹簧配置中)client-secret
  • 正确的授权和范围(在本例中,我使用具有 openid 作用域的authorization_code授权)
  • 正确的重定向回调 ( = 在 spring 配置中)redirect-uri-template
  • 认知中的域配置
  • 一个包含您的认知用户池的 JWK uri(在 spring 配置中)jwk-set-uri

enter image description here

一切就绪后,Spring Boot应用程序将自动生成登录URL

enter image description here

将您重定向到认知登录页面,您可以在其中输入您的认知凭据

enter image description here

身份验证成功后,您将能够执行安全的 REST 调用

enter image description here

使用这样的 REST 控制器:

@RestController
public class ExampleController {

    @RequestMapping("/")
    public String email(Principal principal) {
        return "Hello " + principal.getName();
    }

}

答案 2

我们可以创建Spring Boot资源服务器,将Cognito保留为身份提供者。

Spring boot Resource Server

屬地:

    <!--  Spring Security-->
    <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>

    <dependency>
        <groupId>org.springframework.security.oauth.boot</groupId>
        <artifactId>spring-security-oauth2-autoconfigure</artifactId>
        <version>2.0.1.RELEASE</version>
    </dependency>

弹簧安全配置:

EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class OAuth2ResourceServerSecurityConfiguration extends ResourceServerConfigurerAdapter {

  private final ResourceServerProperties resource;

  public OAuth2ResourceServerSecurityConfiguration(ResourceServerProperties resource) {
    this.resource = resource;
  }

  @Override
  public void configure(HttpSecurity http) throws Exception {

    http.cors();

    http.csrf().disable();

    http.authorizeRequests()
        .antMatchers("/api/public/**").permitAll()
        .antMatchers("/actuator/health").permitAll()
        .anyRequest().authenticated();
  }


  // Note: Cognito Converter
  @Bean
  public TokenStore jwkTokenStore() {
    return new JwkTokenStore(
        Collections.singletonList(resource.getJwk().getKeySetUri()),
        new CognitoAccessTokenConverter(),
        null);
  }
}

认知访问令牌转换器:

在这里,我们将Cognito声明转换为Spring Security可消费格式。

@Component
public class CognitoAccessTokenConverter extends JwtAccessTokenConverter {

  // Note: This the core part.
  private static final String COGNITO_GROUPS = "cognito:groups";
  private static final String SPRING_AUTHORITIES = "authorities";
  private static final String COGNITO_USERNAME = "username";
  private static final String SPRING_USER_NAME = "user_name";

  @SuppressWarnings("unchecked")
  @Override
  public OAuth2Authentication extractAuthentication(Map<String, ?> claims) {

    if (claims.containsKey(COGNITO_GROUPS))
      ((Map<String, Object>) claims).put(SPRING_AUTHORITIES, claims.get(COGNITO_GROUPS));
    if (claims.containsKey(COGNITO_USERNAME))
      ((Map<String, Object>) claims).put(SPRING_USER_NAME, claims.get(COGNITO_USERNAME));
    return super.extractAuthentication(claims);
  }
}

应用程序.属性

server:
  port: 8081
security:
  oauth2:
    resource:
      userInfoUri: https://<cognito>.auth.eu-west-1.amazoncognito.com/oauth2/userInfo
      tokenInfoUri: https://<cognito>.auth.eu-west-1.amazoncognito.com/oauth2/token
      jwk:
        key-set-uri: https://cognito-idp.<region>.amazonaws.com/<user-pool-id>/.well-known/jwks.json
    client:
      clientId: <client-id>

有关完整文章,请参阅:将 Spring Boot 资源服务器与 Cognito Identity Provider 集成


推荐