如何用AWS CDK为RestApi实现Cognito与IAM双授权?
在AWS CDK中为RestApi同时配置Cognito与IAM授权
问题背景
我正在重构现有Amplify项目,原项目采用AppSync搭配Cognito和IAM授权模式。现在希望通过AWS CDK构建所有资源,并将AppSync替换为API Gateway,需要实现RestApi同时支持Cognito(认证用户)和IAM(访客访问)双授权模式。
AppSync中可以直接指定双授权模式,示例代码如下:
const api = new GraphqlApi(this, 'TodoTestAPI', { name: 'TodoTestAPI', schema: Schema.fromAsset(path.join(__dirname, 'schema.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: AuthorizationType.USER_POOL, userPoolConfig: { userPool, }, }, additionalAuthorizationModes: [ { authorizationType: AuthorizationType.IAM, }, ], }, });
我当前的RestApi CDK代码如下,目前仅配置了IAM授权:
const api = new RestApi(this, `RestApi`, { defaultMethodOptions: { authorizationType: AuthorizationType.IAM, }, defaultCorsPreflightOptions: { allowOrigins: Cors.ALL_ORIGINS, allowMethods: Cors.ALL_METHODS, }, cloudWatchRole: true, });
实现方案
API Gateway的RestApi与AppSync的授权配置逻辑不同:AppSync是在API层面统一设置默认和附加授权模式,而RestApi需要在方法层面配置多授权类型。以下是具体实现步骤:
1. 准备Cognito资源(若未创建)
首先确保你已有Cognito用户池和用户池客户端,若没有则通过CDK创建:
import { UserPool, UserPoolClient } from 'aws-cdk-lib/aws-cognito'; // 创建Cognito用户池 const userPool = new UserPool(this, 'MyUserPool', { userPoolName: 'MyAppUserPool', // 根据你的需求配置用户池属性,比如验证方式、密码规则等 }); // 创建用户池客户端 const userPoolClient = new UserPoolClient(this, 'MyUserPoolClient', { userPool, clientName: 'MyAppClient', });
2. 创建Cognito授权器
在API Gateway中,需要先创建Cognito用户池授权器,用于验证Cognito生成的ID Token:
import { CognitoUserPoolsAuthorizer } from 'aws-cdk-lib/aws-apigateway'; const cognitoAuthorizer = new CognitoUserPoolsAuthorizer(this, 'CognitoAuthorizer', { cognitoUserPools: [userPool], authorizerName: 'CognitoUserPoolAuthorizer', });
3. 配置RestApi支持双授权
你可以选择两种方式配置:全局默认双授权,或者为单个方法单独配置。
方式一:全局默认双授权(所有方法默认支持IAM+Cognito)
在创建RestApi时,通过defaultMethodOptions设置默认授权类型为IAM,并添加Cognito作为额外授权类型,同时指定Cognito授权器:
import { RestApi, AuthorizationType, Cors } from 'aws-cdk-lib/aws-apigateway'; const api = new RestApi(this, `RestApi`, { defaultMethodOptions: { authorizationType: AuthorizationType.IAM, // 默认启用IAM授权(访客访问) additionalAuthorizationTypes: [AuthorizationType.COGNITO], // 添加Cognito授权类型 authorizer: cognitoAuthorizer, // 指定Cognito授权器 }, defaultCorsPreflightOptions: { allowOrigins: Cors.ALL_ORIGINS, allowMethods: Cors.ALL_METHODS, }, cloudWatchRole: true, });
方式二:为单个方法单独配置双授权
如果仅部分方法需要双授权,可以在创建方法时覆盖默认配置:
// 先创建基础RestApi(默认仅IAM授权) const api = new RestApi(this, `RestApi`, { defaultMethodOptions: { authorizationType: AuthorizationType.IAM, }, defaultCorsPreflightOptions: { allowOrigins: Cors.ALL_ORIGINS, allowMethods: Cors.ALL_METHODS, }, cloudWatchRole: true, }); // 创建资源和方法,为该方法添加Cognito授权 const todosResource = api.root.addResource('todos'); // 假设已创建Lambda集成(替换为你的实际集成,比如Lambda、HTTP等) import { LambdaIntegration } from 'aws-cdk-lib/aws-apigateway'; import { Function, Runtime, Code } from 'aws-cdk-lib/aws-lambda'; const todoLambda = new Function(this, 'TodoLambda', { runtime: Runtime.NODEJS_20_X, handler: 'index.handler', code: Code.fromAsset('lambda'), }); // 为GET方法配置双授权 todosResource.addMethod('GET', new LambdaIntegration(todoLambda), { authorizationType: AuthorizationType.IAM, additionalAuthorizationTypes: [AuthorizationType.COGNITO], authorizer: cognitoAuthorizer, });
关键说明
- API Gateway允许一个方法同时支持多种授权类型,请求只要通过其中一种授权验证即可访问。
- IAM授权依赖于AWS签名的请求(如通过Amplify的
Auth.signIn后获取的凭证,或访客的匿名角色)。 - Cognito授权依赖于Cognito用户池生成的ID Token,需要在请求头中携带
Authorization: Bearer <ID_TOKEN>。
内容的提问来源于stack exchange,提问作者0xAPPA
相关产品推荐
相关产品推荐

