如何在不使用API​​网关进行自定义Spring REST API授权的情况下使用AWS Cognito

时间:2019-11-20 06:06:11

标签: api authorization amazon-cognito spring-rest

场景:
我将在任何EC2中运行Spring Boot REST API应用程序,并公开多个API,而我不使用AWS API Gateway。
我需要多个用户才能访问具有不同角色(Admin,WriteUser,ReadUser)的多个API。
我可以在Cognito Userpool中创建“用户和组”,并且可以在IAM中具有多个角色。

如何配置AWS Cognito的UserPool和IdentityPool以根据用户角色授权不同的API访问?是否可以在不使用API​​网关的情况下在Policy(与IdentityPool /资源服务器相关联)中定义此类“基于角色的API允许规则”。

谢谢。

3 个答案:

答案 0 :(得分:1)

我使用带有自定义JWTFilter的Spring安全auth2来实现,它将从请求中获取令牌并再次验证cognito池的JWKs验证文件。

  • 用户在用户界面中输入用户名/密码。
  • UI调用后端应用程序,后者调用Cognito。
  • Cognito返回JWT令牌(Idtoken,accessToken,refreshToken)
  • 后端应用程序将IdToken作为令牌发送到UI,并存储在缓存中(也可以是任何数据库)。
  • UI将此IDToken发送给下一次调用。

JWTFilter为身份验证执行以下步骤:

  • 后端应用程序获取令牌,在缓存中进行验证(如果存在),然后使用Cognito JWK验证签名和有效期并从中获取详细信息。
  • 后端应用程序创建扩展了AbstractAuthenticationToken的UserAuthentication,并从解析的令牌值填充详细信息并存储在上下文(会话)中

将按照网络安全配置中提到的配置对资源进行授权。

答案 1 :(得分:1)

我们可以创建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>

Spring Security配置:

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消耗品格式。

对于授权,我们将使用Cognito组。我们创建两个组,ROLE_ADMIN和ROLE_EMPLOYEE。我们将用户映射到每个组。验证用户身份后,我们将Cognito组作为声明。我们利用它来为用户设置Spring Security Authority。

Cognito Groups

@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);
  }
}

application.properties

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>

有关完整的文章,请参见:Integrate Spring Boot Resource Server with Cognito Identity Provider

答案 2 :(得分:0)

您需要在Spring安全性中实现JWT令牌方法(可以使用spring security auth 2 impl。)

因此,身份验证步骤如下:

  • 用户将在您的前端应用程序中输入其凭据。
  • 您的身份验证服务会将这些凭证发送到AWS Cognito进行验证。
  • 如果用户凭证将在AWS Cognito用户响应的帮助下进行验证,则您将创建有效负载,然后创建JWT令牌。
  • 使用公钥-私钥对JWT令牌签名,以便您可以与其他服务共享公钥以验证JWT令牌。
  • 然后,JWT令牌返回到前端应用程序。
  • 现在,Spring Security将为您保护所有私有路线。
  • 您还需要创建一个过滤器,以便当前端应用在标头中附加JWT并向服务器创建ant请求时,您的过滤器将验证JWT令牌(作为身份验证标头),如果该令牌有效,则将创建当前请求的安全上下文,否则抛出401状态。