为什么API Gateway用Authorizer时仅ID token验证通过,access token失败?
问题描述
我有一个 Lambda 函数用于为用户池中的已有用户生成令牌,但是在 API 网关验证时,访问令牌返回401错误,使用 ID 令牌验证则返回200状态码。
核心代码
function asyncAuthenticateUser(cognitoUser, cognitoAuthenticationDetails) { return new Promise(function(resolve, reject) { cognitoUser.authenticateUser(cognitoAuthenticationDetails, { onSuccess: resolve, onFailure: reject }); }); } var authenticationData = { Username: name, Password: password, }; var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData); var poolData = { UserPoolId: UserPoolId, ClientId: ClientId }; var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData); var userData = { Username: name, Pool: userPool }; var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData); try { let session = await asyncAuthenticateUser(cognitoUser, authenticationDetails); cognitoJWT.session = session; console.log(session.getIdToken()); cognitoJWT.jwtAccess = session.getAccessToken().getJwtToken(); cognitoJWT.jwtId = session.getIdToken().getJwtToken(); cognitoJWT.jwtRefresh = session.getRefreshToken().getToken(); cognitoJWT.jwtPayloads = { jwtAccess: session.getAccessToken().decodePayload(), jwtId: session.getIdToken().decodePayload(), }; callback(null, cognitoJWT); } catch (err){callback(err,null); }
Lambda 输出示例
{ "StatusCode": 200, "StatusMessage": { "jwtAccess": "<<jwtAccess>>", "jwtRefresh":"<<jwtRefresh>>", "jwtId":<<jwtId>> } }
问题原因及解决方案
核心原因
Cognito 生成的 ID 令牌和访问令牌的声明规则不同,API 网关 JWT 授权器的配置和访问令牌的声明不匹配会直接导致401错误。
排查和修复步骤
- 核对授权器受众配置
- ID 令牌的
aud(受众)声明默认是 Cognito 用户池客户端 ID,和多数人默认配置的授权器受众匹配,所以验证可以通过 - 访问令牌的
aud声明不是客户端 ID,其携带客户端标识的字段是client_id,aud的值为 Cognito 用户池的服务地址,格式为https://cognito-idp.<部署区域>.amazonaws.com/<用户池ID> - 如需同时支持两种令牌验证,直接在授权器的受众列表中同时添加「客户端 ID」和「用户池服务地址」即可
- ID 令牌的
- 核对授权器签发者配置
- 确认签发者配置完全和 Cognito 用户池的
iss字段一致,无多余斜杠、大小写完全匹配,格式和上述用户池服务地址完全相同
- 确认签发者配置完全和 Cognito 用户池的
- 核对接口作用域配置
- 若对应 API 路由配置了要求特定 OAuth 作用域,需要确认你获取令牌时已经申请了对应作用域,缺少对应作用域也会返回401
快速定位方法
将验证失败的访问令牌解码后,对比 payload 中的iss、aud、client_id字段和你配置的授权器参数,即可快速找到不匹配项。
内容的提问来源于stack exchange,提问作者Santiago Bocel
相关产品推荐
相关产品推荐

