spring 如何配置Sping Boot 以使用AWS Cognito(OAuth2/OIDC)对Web应用用户和REST客户端进行身份验证

vfh0ocws  于 2022-11-28  发布在  Spring
关注(0)|答案(1)|浏览(405)

我需要配置Sping Boot 服务器,以使用AWS Cognito用户池对Web用户和REST客户端进行身份验证:
1.使用ReachJS前端的交互式/Web用户应重定向到Cognito进行身份验证,并在验证用户的凭据后重定向回来。
1.其他直接使用服务器REST API的机器应该从Cognito获得一个令牌,并将其作为Authorization: Bearer ...头发送到我的服务器。
问题是:
1.如何配置spring以使用Cognito进行身份验证
1.如何使spring同时支持这两种不同类型的身份验证

os8fio9y

os8fio9y1#

概述

让我们从术语开始:

  1. IDP(身份提供商)是提供用户管理和身份验证服务的第三方,在我的案例中是AWS Cognito。
    1.在OAuth2/OIDC中,通过将交互式/Web用户重定向到IDP来对交互式/Web用户进行身份验证称为“授权代码授予流程.”
    1.将JWT令牌发送到REST API的客户端称为“客户端凭据流”。
    Spring的spring-security-oauth2-client模块负责“授权代码授予流”,spring-security-oauth2-resource-server模块负责“客户端凭证流”。
    为了同时使用这两个流/方法,我们需要告诉spring如何确定传入的HTTP请求使用哪种身份验证方法,正如https://stackoverflow.com/a/64752665/2692895中所解释的,这可以通过查找Authorization: bearer ...头来完成:
    1.如果请求包含Authorization头,则假定它是REST客户机并使用“客户机凭据流”。
    1.否则,它是一个交互式用户,如果尚未进行身份验证,则重定向到Cognito。

依赖项

我使用的是Spring Boot2.6.6(Spring5.6.2)。

<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>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-resource-server</artifactId>
        </dependency>

外部配置-application.yaml

spring:
  security:
    oauth2:
      # Interactive/web users authentication
      client:
        registration:
          cognito:
            clientId: ${COGNITO_CLIENT_ID}
            clientSecret: ${COGNITO_CLIENT_SECRET}
            scope: openid
            clientName: ${CLIENT_APP_NAME}
        provider:
          cognito:
            issuerUri: https://cognito-idp.eu-central-1.amazonaws.com/${COGNITO_POOL_ID}
            user-name-attribute: email

      # REST API authentication
      resourceserver:
        jwt:
          issuer-uri: https://cognito-idp.eu-central-1.amazonaws.com/${COGNITO_POOL_ID}

Spring安全配置

交互式/Web用户身份验证:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
    // Needed for method access control via the @Secured annotation
    prePostEnabled = true,
    jsr250Enabled = true,
    securedEnabled = true
)
@Profile({"cognito"})
@Order(2)
public class CognitoSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @SneakyThrows
    @Override
    protected void configure(HttpSecurity http) {
        http
            // TODO disable CSRF because when enabled controllers aren't initialized
            //  and if they are, POST are getting 403
            .csrf().disable()

            .authorizeRequests()
            .anyRequest().authenticated()

            .and()
            .oauth2Client()

            .and()
            .logout()

            .and()
            .oauth2Login()
            .redirectionEndpoint().baseUri("/login/oauth2/code/cognito")
            .and()
        ;
    }
}

REST客户端身份验证:

/**
 * Allow users to use a token (id-token, jwt) instead of the interactive login.
 * The token is specified as the "Authorization: Bearer ..." header.
 * </p>
 * To get a token, the cognito client-app needs to support USER_PASSWORD_AUTH then use the following command:
 * <pre>
 *     aws cognito-idp initiate-auth --auth-flow USER_PASSWORD_AUTH --output json \
 *         --region $region --client-id $clientid --auth-parameters "USERNAME=$username,PASSWORD=$password" \
 *         | jq .AuthenticationResult.IdToken
 * </pre>
 */
@Slf4j
@Configuration
@Profile({"cognito"})
@Order(1)
public class CognitoTokenBasedSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @SneakyThrows
    @Override
    protected void configure(HttpSecurity http) {
        http
            .requestMatcher(new RequestHeaderRequestMatcher("Authorization"))
            .authorizeRequests().anyRequest().authenticated()
            .and().oauth2ResourceServer().jwt()
        ;
    }

}

Cognito配置说明

  • 在AWS Cognito中,您需要创建一个用户池和两个客户端应用程序,一个用于交互/Web用户的“公共客户端”,一个用于基于令牌的REST客户端的“机密客户端”。
  • 在“公共客户端”中,确保为所有环境(本地主机、生产等)定义“允许的回调URL”,它们都应该类似于http://localhost:8080/login/oauth2/code/cognito(当然要有正确的主机名和端口)。

相关问题