aws-samples/sample-cognito-m2m-token-cache-on-aws

GitHub: aws-samples/sample-cognito-m2m-token-cache-on-aws

为 Amazon Cognito 的机器到机器(M2M)认证场景提供带有智能响应缓存和 WAF 防旁路安全防护的 API Gateway 代理方案。

Stars: 3 | Forks: 0

# 带有缓存功能的 Amazon Cognito OAuth2 Token 代理 一个用于 Amazon Cognito 的 OAuth2 token 端点的 Amazon API Gateway 代理,它增加了智能缓存功能,从而降低成本、提高性能,并提升机器到机器 (M2M) 认证场景的可扩展性。 本仓库提供了 AWS Security 博客文章中所述架构的可部署实现:[如何监控、优化和保护 Amazon Cognito 的机器到机器授权](https://aws.amazon.com/blogs/security/how-to-monitor-optimize-and-secure-amazon-cognito-machine-to-machine-authorization/)。 ## 目录 - [架构](#architecture) - [完整架构](#full-architecture) - [请求流程 — 直接访问被阻止](#request-flow--direct-access-blocked) - [请求流程 — 通过 API Gateway](#request-flow--via-api-gateway) - [组件](#components) - [用法](#usage) - [身份验证方法](#authentication-methods) - [响应格式](#response-format) - [测试](#testing) - [监控](#monitoring) - [安全最佳实践](#security-best-practices) - [前置条件](#prerequisites) - [部署](#deployment) - [使用 AWS CDK 部署(推荐)](#deploy-with-aws-cdk-recommended) - [使用 CloudFormation 部署(高级 — 不包含 WAF)](#deploy-with-cloudformation-advanced--without-waf) - [访问应用](#accessing-the-application) - [移除应用](#remove-the-application) - [贡献](#contributing) - [许可证](#license) ## 架构 该解决方案部署了一个 Amazon API Gateway REST API,用于将请求代理到 Amazon Cognito 的 OAuth2 token 端点,并提供了缓存、WAF 保护和基于 Secrets Manager 的 origin-verify 验证机制。 ### 完整架构 ![完整架构](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/076b479764194833.png) 该架构由以下协同工作的组件组成。客户端应用程序向 Amazon API Gateway REST API(区域端点)发送 OAuth2 token 请求,该 API 充当 Amazon Cognito 前面的代理。在将请求转发给 Cognito 之前,API Gateway 会检查其内置的响应缓存,该缓存以 Authorization 头和 scope 查询参数为键。在缓存命中时,会立即返回缓存的 token,无需联系 Cognito,从而减少了延迟和成本。在缓存未命中时,API Gateway 会注入一个秘密的 `x-origin-verify` 头(源自 Secrets Manager,通过阶段变量传入),并通过 AWS WAF 将客户端凭证授权请求转发到 Cognito User Pool 的 `/oauth2/token` 端点。WAF 验证 origin-verify 头并阻止任何未包含该头的请求,从而防止直接访问 Cognito。响应将被缓存设定的 TTL 时间并返回给调用者。整个基础设施通过 AWS CDK 部署。 #### 成本降低示例 考虑一个每 5 分钟请求一次新访问 token 的应用程序(每小时 12 次)。如果 token 过期时间为 1 小时,使用此缓存解决方案: - **不使用缓存**:每小时 12 次 Cognito API 调用 = 每个应用程序每天 288 次调用 - **使用缓存**:每小时 1 次 Cognito API 调用 = 每个应用程序每天 24 次调用 - **降低幅度**:减少了 91.7% 的 Cognito API 调用 对于发出类似请求的 100 个应用程序: - **不使用缓存**:每天 28,800 次 Cognito 调用 - **使用缓存**:每天 2,400 次 Cognito 调用 - **每月节省**:减少约 792,000 次 Cognito API 调用 M2M token 请求的这种减少可直接转化为成本节约。有关当前定价详情,请参阅 [Amazon Cognito 定价页面](https://aws.amazon.com/cognito/pricing/)。 ### 请求流程 — 直接访问被阻止 当客户端尝试直接访问 Cognito(绕过 API Gateway)时,WAF 会阻止该请求: ``` sequenceDiagram participant Client as Client Application participant WAF as AWS WAF participant Cognito as Amazon Cognito Client->>WAF: 1. Direct POST to Cognito /oauth2/token WAF->>WAF: 2. Inspect request: no x-origin-verify header WAF--xClient: 3. 403 Forbidden Note over WAF,Cognito: Request never reaches Cognito ``` ### 请求流程 — 通过 API Gateway 当客户端通过 API Gateway 进行访问时,会注入 origin-verify 头,WAF 将允许该请求: ``` sequenceDiagram participant Client as Client Application participant APIGW as API Gateway participant Cache as Response Cache participant SM as Secrets Manager participant WAF as AWS WAF participant Cognito as Amazon Cognito Client->>APIGW: 1. POST /oauth2/token APIGW->>Cache: 2. Check cache (Authorization + scope) alt Cache Hit Cache-->>APIGW: 3a. Return cached token APIGW-->>Client: 4a. Return cached token else Cache Miss Cache-->>APIGW: 3b. No cached token SM-->>APIGW: 4b. Provide x-origin-verify token (stage variable) APIGW->>WAF: 5. Forward request with x-origin-verify header WAF->>WAF: 6. Validate x-origin-verify header WAF->>Cognito: 7. Header valid — allow request Cognito-->>APIGW: 8. Return access token APIGW->>Cache: 9. Cache token (TTL-based) APIGW-->>Client: 10. Return access token end ``` ### 组件 - **Amazon API Gateway**:具有 `/oauth2/token` 端点的区域 REST API,用于将请求代理到 Cognito - **API Gateway Cache**:可配置的缓存集群(0.5GB - 237GB),具有基于 TTL 的过期机制,用于存储 token - **AWS WAF**:WebACL,在允许直接 Cognito 访问之前验证自定义的 origin-verify 头 - **Amazon Cognito User Pool**:用于客户端凭证流的 OAuth2 token 端点 - **AWS Secrets Manager**:存储 API Gateway 和 WAF 使用的 origin-verify 密钥 - **CloudWatch Logs**:API Gateway 请求的访问日志 - **AWS X-Ray**:用于请求监控的分布式追踪 ## 用法 ### 身份验证方法 代理支持三种提供 OAuth2 凭证的方法: #### 方法一:Authorization 头(推荐) ``` curl -X POST "https://API_ID.execute-api.REGION.amazonaws.com/STAGE/oauth2/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" \ -d "grant_type=client_credentials&scope=your/scope" ``` #### 方法二:请求体参数 ``` curl -X POST "https://API_ID.execute-api.REGION.amazonaws.com/STAGE/oauth2/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&scope=your/scope" ``` #### 方法三:查询参数 ``` curl -X POST "https://API_ID.execute-api.REGION.amazonaws.com/STAGE/oauth2/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&scope=your%2Fscope" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" ``` scope 可以在请求体中传递(方法一和方法二),也可以作为查询字符串参数传递(方法三)。使用方法三时,scope 值在查询字符串中必须进行 URL 编码。缓存通过凭证和 scope 隔离 token,因此不同的 scope 会生成不同的缓存 token。 ### 响应格式 成功的请求将返回 JSON 响应: ``` { "access_token": "eyJraWQiOiJ...", "expires_in": 3600, "token_type": "Bearer" } ``` ### 测试 有关全面的测试说明,包括 API Gateway 测试和 WAF 保护验证,请参阅[测试指南](docs/testing-guide.md)。 ### 监控 使用 Amazon CloudWatch 指标监控解决方案: - **CacheHitCount / CacheMissCount**:衡量缓存有效性 - **Count**:请求总数 - **Latency**:响应时间 - **4XXError / 5XXError**:错误率 ``` # Cache 命中 aws cloudwatch get-metric-statistics \ --namespace AWS/ApiGateway \ --metric-name CacheHitCount \ --dimensions Name=ApiName,Value=CognitoAuthProxy \ --start-time $(date -u -v-1H +%Y-%m-%dT%H:%M:%S)Z \ --end-time $(date -u +%Y-%m-%dT%H:%M:%S)Z \ --period 300 \ --statistics Sum \ --profile YOUR_AWS_PROFILE # Cache 未命中 aws cloudwatch get-metric-statistics \ --namespace AWS/ApiGateway \ --metric-name CacheMissCount \ --dimensions Name=ApiName,Value=CognitoAuthProxy \ --start-time $(date -u -v-1H +%Y-%m-%dT%H:%M:%S)Z \ --end-time $(date -u +%Y-%m-%dT%H:%M:%S)Z \ --period 300 \ --statistics Sum \ --profile YOUR_AWS_PROFILE # 平均延迟 aws cloudwatch get-metric-statistics \ --namespace AWS/ApiGateway \ --metric-name Latency \ --dimensions Name=ApiName,Value=CognitoAuthProxy \ --start-time $(date -u -v-1H +%Y-%m-%dT%H:%M:%S)Z \ --end-time $(date -u +%Y-%m-%dT%H:%M:%S)Z \ --period 300 \ --statistics Average \ --profile YOUR_AWS_PROFILE ``` ### 安全最佳实践 此解决方案实现了多层安全防护:仅限 HTTPS 流量、静态加密缓存、区域端点、WAF 保护、访问日志和 X-Ray 追踪。 - 为 API Gateway 启用 AWS CloudTrail 日志记录 - 在 Amazon CloudWatch 中监控 API Gateway 指标 - 根据 token 过期时间设置适当的缓存 TTL - 实施存储在 Secrets Manager 中的 origin-verify 密钥的定期轮换。轮换时,更新 WAF 规则以在过渡期间同时接受新旧密钥值,然后使用新值更新 API Gateway 阶段变量,最后从 WAF 规则中移除旧值 ## 前置条件 在部署此解决方案之前,您必须具备以下条件: - 一个 [AWS 账户](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/) - 一个配置了 OAuth2 客户端凭证的 Amazon Cognito User Pool - 一个 Cognito 域名(Amazon Cognito 托管域) - [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 2.x 或更高版本,并配置了适当的凭证 - 对于 CDK 部署(推荐): - [Python](https://www.python.org/downloads/) >= 3.8 - [Node.js](https://nodejs.org/) >= 20.x - [AWS CDK CLI](https://docs.aws.amazon.com/cdk/v2/guide/getting-started.html) >= 2.x (`npm install -g aws-cdk`) ## 部署 ### 使用 AWS CDK 部署(推荐) 强烈推荐使用 CDK 部署。它部署了包含 WAF 保护的完整解决方案,以防止直接访问 Cognito。API Gateway 会在每个代理请求中注入一个秘密的 `x-origin-verify` 头(存储在 Secrets Manager 中),而 WAF 会阻止任何不包含该头的 Cognito 请求。 #### 第 1 步:克隆仓库 ``` git clone https://github.com/aws-samples/sample-cognito-m2m-token-cache-on-aws.git cd sample-cognito-m2m-token-cache-on-aws ``` #### 第 2 步:设置 Python 虚拟环境 ``` cd cdk python3 -m venv .venv source .venv/bin/activate # On Windows: .venv\Scripts\activate pip install -r requirements.txt ``` #### 第 3 步:引导 CDK(仅限首次) 如果是首次在您的账户/区域中部署 CDK,您需要引导 CDK 工具包: ``` cdk bootstrap aws://ACCOUNT/REGION --profile YOUR_AWS_PROFILE ``` 这将创建 CDK 部署堆栈所需的 S3 存储桶和 IAM 角色。每个账户/区域组合只需执行一次此操作。 #### 第 4 步:配置并部署 ``` cdk deploy \ --profile YOUR_AWS_PROFILE \ -c cognito_domain=YOUR_COGNITO_DOMAIN.auth.REGION.amazoncognito.com \ -c cognito_user_pool_arn=arn:aws:cognito-idp:REGION:ACCOUNT:userpool/POOL_ID \ -c stage_name=dev \ -c cache_ttl_seconds=3600 \ -c cache_size_gb=0.5 \ --outputs-file ../cdk-outputs.json ``` 替换以下值: - `YOUR_AWS_PROFILE`:您的 AWS CLI 配置文件名称 - `YOUR_COGNITO_DOMAIN`:不带 `https://` 的 Cognito 域名 - `REGION`:您的 AWS 区域(例如,`us-east-1`) - `ACCOUNT`:您的 AWS 账户 ID - `POOL_ID`:您的 Cognito User Pool ID 部署大约需要 2-3 分钟。部署完成后,堆栈输出包括: - `ApiEndpointOutput`:API Gateway 端点 URL - `WebACLOutput`:WAF WebACL ARN **注意**:部署后,WAF 与 Cognito 的关联可能需要 5-10 分钟才能传播生效。 ### 使用 CloudFormation 部署(高级 — 不包含 WAF) 我们为已有 WAF 部署或倾向于单独管理 WAF 的用户提供了一个独立的 CloudFormation 模板 (`cognito-proxy-template.yaml`)。此模板仅部署 API Gateway 缓存代理,不包含 WAF 保护。您需要自行负责配置 WAF 以阻止对您的 Cognito User Pool 的直接访问。 #### 第 1 步:验证模板 ``` aws cloudformation validate-template \ --template-body file://cognito-proxy-template.yaml \ --profile YOUR_AWS_PROFILE ``` #### 第 2 步:部署堆栈 ``` aws cloudformation deploy \ --template-file cognito-proxy-template.yaml \ --stack-name cognito-oauth-proxy \ --capabilities CAPABILITY_IAM \ --parameter-overrides \ CognitoDomain=YOUR_COGNITO_DOMAIN.auth.REGION.amazoncognito.com \ StageName=dev \ CacheTtlInSeconds=3600 \ CacheSize=0.5 \ --profile YOUR_AWS_PROFILE ``` #### 第 3 步:获取堆栈输出 ``` aws cloudformation describe-stacks \ --stack-name cognito-oauth-proxy \ --query 'Stacks[0].Outputs' \ --profile YOUR_AWS_PROFILE ``` ## 访问应用 部署后,从堆栈输出中获取 API 端点: 1. `ApiEndpointOutput` 提供的 URL 为:`https://.execute-api..amazonaws.com//oauth2/token` 2. 使用上述任意一种[身份验证方法](#authentication-methods)发送 token 请求。 有关详细的测试场景,请参阅[测试指南](docs/testing-guide.md)。 ## 移除应用 为避免产生未来费用,请删除此解决方案创建的资源。 ### 删除 CDK 堆栈 ``` cd cdk cdk destroy --profile YOUR_AWS_PROFILE ``` **注意**:在删除之前,您可能需要手动取消 WAF WebACL 与 Cognito User Pool 的关联: ``` aws wafv2 disassociate-web-acl \ --resource-arn arn:aws:cognito-idp:REGION:ACCOUNT:userpool/POOL_ID \ --profile YOUR_AWS_PROFILE \ --region REGION ``` ### 删除 CloudFormation 堆栈 ``` aws cloudformation delete-stack \ --stack-name cognito-oauth-proxy \ --profile YOUR_AWS_PROFILE ``` ## 贡献 欢迎贡献!请阅读 [CONTRIBUTING.md](CONTRIBUTING.md) 文件以获取有关如何为此项目做贡献的指南。有关社区标准,请参阅[行为准则](CODE_OF_CONDUCT.md)。 ## 许可证 本库基于 MIT-0 许可证授权。详情请参阅 [LICENSE](LICENSE) 文件。
标签:Amazon API Gateway, Amazon Cognito, API安全, AWS, AWS CDK, AWS WAF, CISA项目, CloudFormation, DPI, IAM, JSON输出, M2M认证, OAuth2, REST API, Secrets Manager, Streamlit, WAF, 代理, 令牌端点, 安全, 性能优化, 成本优化, 授权, 无文件攻击, 无服务器, 机器对机器, 检测绕过, 缓存, 网络安全, 访问控制, 超时处理, 身份与访问管理, 逆向工具, 隐私保护