使用amazon-cognito-identity SDK获取的JWT令牌授权失败问题排查
问题描述
我们配置了一个Cognito用户池,将OAuth 2.0隐式授权设为允许的OAuth流程,希望基于JS的Web应用能通过在请求Authorization头中携带Cognito JWT令牌,调用带有API Gateway端点的Lambda函数。
测试情况:
- 通过Postman使用默认Cognito托管UI登录,从跳转URL中复制
access_token,可以正常调用Lambda函数。 - 使用
amazon-cognito-identity.min.jsSDK的authenticateUser函数认证(应用基于jQuery开发),认证成功,但返回的JWT令牌无效——复制到Postman调用同一接口时返回"Unauthorized"。同时测试ID令牌(result.getIdToken().getJwtToken())也无效,且SDK返回的令牌比托管UI生成的更长。
相关JS代码:
var authentication_details = new AmazonCognitoIdentity.AuthenticationDetails({ Username: email, Password: $('#password').val(), }); var cognito_user = new AmazonCognitoIdentity.CognitoUser({ Username: email, Pool: cognito_user_pool }); cognito_user.authenticateUser(authentication_details, { onSuccess: function (result) { var jwt_token = result.getAccessToken().getJwtToken(); // 此令牌无效,且比托管UI生成的令牌更长 // ...后续代码 } });
问题原因与解决方案
核心原因
使用authenticateUser方法直接认证时,Cognito返回的是用户池令牌,而托管UI通过OAuth隐式授权流程返回的是OAuth令牌。这两类令牌的受众(aud)和用途不同:
- 用户池令牌的
aud是用户池ID,仅适用于Cognito内部操作(比如获取用户信息); - OAuth令牌的
aud是你配置的应用客户端ID,才能被API Gateway的Cognito授权器识别。
解决步骤
使用OAuth隐式授权流程获取有效令牌
不要直接调用authenticateUser,而是引导用户跳转到Cognito托管UI完成登录,通过OAuth隐式授权流程获取access_token。这种方式和你Postman测试的流程一致,返回的令牌可以直接用于API Gateway调用。调整SDK调用方式(无需跳转托管UI)
如果必须在应用内完成登录而不跳转,需要在用户池应用客户端配置中启用ALLOW_USER_PASSWORD_AUTH授权流程,然后使用initiateAuth方法获取符合OAuth标准的令牌:- 登录AWS控制台,进入Cognito用户池的应用客户端设置,启用
ALLOW_USER_PASSWORD_AUTH流程; - 使用以下代码调用接口获取有效令牌:
var cognitoIdentityServiceProvider = new AWS.CognitoIdentityServiceProvider({ region: '你的AWS区域' }); var params = { AuthFlow: 'USER_PASSWORD_AUTH', ClientId: '你的应用客户端ID', AuthParameters: { 'USERNAME': email, 'PASSWORD': $('#password').val() } }; cognitoIdentityServiceProvider.initiateAuth(params, function(err, data) { if (err) { console.log(err); } else { var validAccessToken = data.AuthenticationResult.AccessToken; // 使用此令牌调用API Gateway } });
- 登录AWS控制台,进入Cognito用户池的应用客户端设置,启用
验证令牌内容
可以用本地JWT解码工具对比两类令牌的aud、iss等字段,确认用户池令牌和OAuth令牌的差异,确保使用的令牌符合API Gateway授权器的要求。
内容的提问来源于stack exchange,提问作者Mert
相关产品推荐
相关产品推荐

