Serverless架构下AWS Cognito登录IdToken返回undefined问题
问题分析与解决方案
问题原因
从返回的响应可以看到,Cognito返回了NEW_PASSWORD_REQUIRED挑战,这说明当前用户是首次登录,或是被管理员要求重置密码,此时认证流程尚未完成,因此不会返回包含IdToken的AuthenticationResult字段,仅会返回Session和挑战参数。
解决方案
需要处理密码重置挑战,完整认证流程分为两步:
- 首次调用
adminInitiateAuth,若收到NEW_PASSWORD_REQUIRED挑战,将Session和必填属性要求返回给前端,引导用户输入新密码及必填属性(如响应中的nickname) - 前端提交新信息后,调用
adminRespondToAuthChallenge完成认证,此时即可获取IdToken
修改后的Lambda代码示例
export async function login( event: APIGatewayEvent, context: Context ): Promise<APIGatewayProxyResult> { const body = JSON.parse(event.body!); let { email, password, newPassword, nickname } = body; try { // 发起初始认证请求 const authParams = { AuthFlow: "ADMIN_NO_SRP_AUTH", UserPoolId: "MY_POOL_ID", ClientId: "MY_CLIENT_ID", AuthParameters: { USERNAME: email, PASSWORD: password, }, }; const authResponse = await cognito.adminInitiateAuth(authParams).promise(); // 处理NEW_PASSWORD_REQUIRED挑战 if (authResponse.ChallengeName === "NEW_PASSWORD_REQUIRED") { // 若前端已提交新密码和属性,直接响应挑战 if (newPassword && nickname) { const challengeParams = { UserPoolId: "MY_POOL_ID", ClientId: "MY_CLIENT_ID", ChallengeName: "NEW_PASSWORD_REQUIRED", Session: authResponse.Session, ChallengeResponses: { USERNAME: email, NEW_PASSWORD: newPassword, "userAttributes.nickname": nickname }, }; const challengeResponse = await cognito.adminRespondToAuthChallenge(challengeParams).promise(); return { statusCode: 200, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify({ token: challengeResponse.AuthenticationResult?.IdToken, expires: challengeResponse.AuthenticationResult?.ExpiresIn, }), }; } else { // 前端未提交新信息,返回挑战要求 return { statusCode: 200, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify({ challenge: "NEW_PASSWORD_REQUIRED", session: authResponse.Session, requiredAttributes: JSON.parse(authResponse.ChallengeParameters.requiredAttributes) }), }; } } // 正常认证成功,返回Token return { statusCode: 200, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify({ token: authResponse.AuthenticationResult?.IdToken, expires: authResponse.AuthenticationResult?.ExpiresIn, }), }; } catch (error) { return { statusCode: 401, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify({ message: "认证失败", error: error.message }), }; } }
关键说明
- 当用户处于首次登录或密码重置状态时,Cognito会触发
NEW_PASSWORD_REQUIRED挑战,必须完成该挑战才能获取IdToken - 前端需处理两种场景:直接接收返回的Token,或收到挑战后展示表单让用户输入新密码和必填属性
- 响应挑战时,必须携带之前获取的Session,且需提供
requiredAttributes中要求的所有属性
内容的提问来源于stack exchange,提问作者Nikoo
相关产品推荐
相关产品推荐

