通过Google登录Cognito后调用getSession获取会话失败求助
问题描述
在React项目中使用amazon-cognito-identity-js库配置Cognito Google授权登录,用户已成功在用户池中创建。通过以下代码跳转至Cognito托管登录页完成Google登录:
const path = `https://${myDomain}.auth.us-east-1.amazoncognito.com/login?response_type=code&client_id=${clientId}&redirect_uri=${redirect}`; router.push(path);
登录成功重定向回应用后,调用以下代码尝试获取用户会话时,MyPool.getCurrentUser()返回undefined,触发错误Current user not found:
const getSession = (role: TRoles): Promise<IReturnObj> => { return new Promise((resolve, reject) => { const user = MyPool.getCurrentUser(); if (!user) { reject(new Error('Current user not found')); } user.getSession((err: Error, session: CognitoUserSession) => { if (err) { reject(err); } else { resolve({session, user}); } }); }); };
Cognito应用客户端设置截图:
问题原因及解决步骤
核心问题是:使用授权码流程(response_type=code)跳转登录后,重定向回应用时未处理Cognito返回的授权码,未完成令牌交换并初始化CognitoUser实例,导致getCurrentUser()无法从本地存储读取到用户数据。
1. 处理重定向后的授权码
重定向回应用时URL会携带code参数,需用该授权码交换令牌并完成用户初始化,推荐用amazon-cognito-identity-js内置的CognitoAuth类处理:
import { CognitoAuth } from 'amazon-cognito-identity-js'; const authData = { ClientId: clientId, AppWebDomain: `${myDomain}.auth.us-east-1.amazoncognito.com`, TokenScopesArray: ['openid', 'email', 'profile'], // 根据需求调整权限范围 RedirectUriSignIn: redirect, RedirectUriSignOut: '你的退出重定向地址' }; const auth = new CognitoAuth(authData); auth.userhandler = { onSuccess: (result) => { // 登录成功后Cognito自动将用户数据存入本地存储,此时可调用getSession getSession(role).then(res => { // 处理会话和用户属性 }); }, onFailure: (err) => { console.error('登录失败', err); } }; // 在重定向后的页面初始化时调用,解析Cognito返回的授权码 auth.parseCognitoWebResponse(window.location.href);
2. 检查应用客户端配置
从截图确认以下配置:
- 重定向URI(
redirect_uri)与Cognito应用客户端中配置的完全一致,包括协议、域名、路径,不能有任何差异 - 取消勾选
Generate client secret(前端应用无法安全存储密钥,授权码流程下无需启用)
3. 手动令牌交换与用户初始化(可选)
若不想用CognitoAuth,可手动处理令牌交换并创建CognitoUser实例:
// 从URL中提取授权码 const urlParams = new URLSearchParams(window.location.search); const code = urlParams.get('code'); // 发送请求交换令牌 fetch(`https://${myDomain}.auth.us-east-1.amazoncognito.com/oauth2/token`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'authorization_code', client_id: clientId, code: code, redirect_uri: redirect }) }) .then(res => res.json()) .then(data => { // 创建CognitoUser实例 const userData = { Username: data.id_token_payload.username, // 从id_token的payload中获取用户名 Pool: MyPool }; const cognitoUser = new CognitoUser(userData); // 设置并保存会话 const session = new CognitoUserSession({ IdToken: new CognitoIdToken({ IdToken: data.id_token }), AccessToken: new CognitoAccessToken({ AccessToken: data.access_token }), RefreshToken: new CognitoRefreshToken({ RefreshToken: data.refresh_token }) }); cognitoUser.setSignInUserSession(session); cognitoUser.saveSession(session, (err) => { if (!err) { // 此时getCurrentUser()可正常获取用户 getSession(role).then(res => { // 处理数据 }); } }); }) .catch(err => console.error('令牌交换失败', err));
内容的提问来源于stack exchange,提问作者Олег Верушкин
相关产品推荐
相关产品推荐

