Serverless框架下如何从AWS Cognito获取Access、Id及Refresh Token
问题解答
1. 关于Id Token通过API认证的误解
你的假设不完全准确——AWS API Gateway的Cognito用户池授权器默认同时支持Id Token和Access Token完成认证,所以用Id Token能通过验证是正常行为。但从最佳实践角度:
- Id Token:用于前端获取用户身份信息(如邮箱、用户名),不应用来访问API资源
- Access Token:专门用于访问受保护的API,包含用户权限范围,安全性和权限控制更精准
2. 如何让登录接口返回三个令牌
登录仅返回Id Token,大概率是你的login.handler代码未完整返回Cognito的认证结果,或是调用AdminInitiateAuth时参数配置有误,按以下步骤修复:
步骤1:检查并修正登录函数代码
确保完整获取并返回Cognito响应中的AuthenticationResult对象,该对象包含IdToken、AccessToken和RefreshToken。示例代码:
const AWS = require('aws-sdk'); const cognito = new AWS.CognitoIdentityServiceProvider(); exports.handler = async (event) => { const { username, password } = JSON.parse(event.body); const params = { AuthFlow: 'ADMIN_NO_SRP_AUTH', UserPoolId: process.env.user_pool_id, ClientId: process.env.client_id, AuthParameters: { USERNAME: username, PASSWORD: password } }; try { const response = await cognito.adminInitiateAuth(params).promise(); // 完整返回所有令牌 return { statusCode: 200, body: JSON.stringify({ idToken: response.AuthenticationResult.IdToken, accessToken: response.AuthenticationResult.AccessToken, refreshToken: response.AuthenticationResult.RefreshToken }) }; } catch (error) { return { statusCode: 400, body: JSON.stringify({ message: error.message }) }; } };
步骤2:验证用户池客户端配置
你的Serverless配置中,UserClient的ExplicitAuthFlows已设置ADMIN_NO_SRP_AUTH,这是正确的,额外确保:
GenerateSecret设为false(已配置),避免调用时需要传入SECRET_HASH- 若需自定义刷新令牌有效期,可补充配置
RefreshTokenValidity(默认30天):UserClient: Type: AWS::Cognito::UserPoolClient Properties: # 已有配置... RefreshTokenValidity: 30 # 单位:天
步骤3:确认认证流程参数正确性
调用adminInitiateAuth时,AuthFlow必须严格设为ADMIN_NO_SRP_AUTH,且AuthParameters必须包含USERNAME和PASSWORD,不能遗漏。
额外注意事项
- Access Token过期后,可使用Refresh Token调用
adminInitiateAuth(AuthFlow设为REFRESH_TOKEN_AUTH)获取新的Access Token和Id Token - 若需严格限制仅Access Token可访问API,可改用自定义Lambda授权器,验证令牌的
token_use字段为access
内容的提问来源于stack exchange,提问作者mh377
相关产品推荐
相关产品推荐

