如何在后端提取并验证AWS Cognito Cookie?
我们的认证前端原本通过Authorization请求头向后端传递Bearer令牌,该令牌由React前端从idToken提取,后端已能成功提取并验证。现在为实现同域名多页面共享认证状态、移除JS中的令牌处理代码,打算切换至Cookie认证——配置Amplify时设置了cookieStorage参数,但生成的Cookie名称格式十分复杂:
CognitoIdentityServiceProvider.1pko4kjgrn0c9m7c**********.google_11790661*************.refreshToken CognitoIdentityServiceProvider.1pko4kjgrn0c9m7c**********.LastAuthUser CognitoIdentityServiceProvider.1pko4kjgrn0c9m7c**********.google_11790661*************.clockDrift CognitoIdentityServiceProvider.1pko4kjgrn0c9m7c**********.google_11790661*************.accessToken CognitoIdentityServiceProvider.1pko4kjgrn0c9m7c**********.google_11790661*************.idToken
这些Cookie的值均为预期的JWT,但不想用正则匹配CognitoIdentityServiceProvider\..*\.idToken的方式提取,希望找到更规范的处理方案(搜索到的多数示例仍建议用JS设置Authorization头,不符合需求)。
规范解决方案
1. 前端用Amplify Auth API直接获取令牌
无需手动解析Cookie,Amplify内置API可直接从cookieStorage中读取并解析会话信息:
import { Auth } from 'aws-amplify'; const getCurrentAuthTokens = async () => { try { const session = await Auth.currentSession(); return { idToken: session.getIdToken().getJwtToken(), accessToken: session.getAccessToken().getJwtToken() }; } catch (err) { console.error('获取认证会话失败:', err); return null; } };
这种方式完全避开Cookie命名规则,由Amplify自动处理会话读取逻辑。
2. 后端基于Cognito Cookie规则解析
Cognito的Cookie命名遵循固定格式:CognitoIdentityServiceProvider.<用户池客户端ID>.<用户名>.<令牌类型>,其中LastAuthUser存储当前登录用户名。可以先读取该Cookie的值,再拼接出目标令牌的Cookie名称:
以Node.js后端为例:
const extractCognitoTokensFromCookies = (req, userPoolClientId) => { // 先获取当前登录用户名 const lastAuthUserKey = `CognitoIdentityServiceProvider.${userPoolClientId}.LastAuthUser`; const username = req.cookies[lastAuthUserKey]; if (!username) return null; // 拼接目标令牌的Cookie键名 const idTokenKey = `CognitoIdentityServiceProvider.${userPoolClientId}.${username}.idToken`; const accessTokenKey = `CognitoIdentityServiceProvider.${userPoolClientId}.${username}.accessToken`; return { idToken: req.cookies[idTokenKey], accessToken: req.cookies[accessTokenKey] }; };
这种方式依赖已知的用户池客户端ID,比正则匹配更稳定可靠。
3. 自定义Cookie存储规则(进阶)
如果希望完全控制Cookie名称,可以通过自定义cookieStorage的setItem/getItem/removeItem方法,将关键令牌存为简洁的自定义名称:
import { Auth } from 'aws-amplify'; Auth.configure({ authenticationFlowType: 'USER_SRP_AUTH', cookieStorage: { domain: '.yourdomain.com', path: '/', expires: 365, secure: true, sameSite: 'strict', // 自定义存储逻辑,简化关键令牌的Cookie名称 setItem: (key, value) => { let cookieKey = key; if (key.endsWith('.idToken')) cookieKey = 'app_id_token'; else if (key.endsWith('.accessToken')) cookieKey = 'app_access_token'; document.cookie = `${cookieKey}=${value}; domain=.yourdomain.com; path=/; secure; sameSite=Strict`; }, getItem: (key) => { let cookieKey = key; if (key.endsWith('.idToken')) cookieKey = 'app_id_token'; else if (key.endsWith('.accessToken')) cookieKey = 'app_access_token'; return document.cookie.split('; ').find(row => row.startsWith(`${cookieKey}=`))?.split('=')[1]; }, removeItem: (key) => { let cookieKey = key; if (key.endsWith('.idToken')) cookieKey = 'app_id_token'; else if (key.endsWith('.accessToken')) cookieKey = 'app_access_token'; document.cookie = `${cookieKey}=; domain=.yourdomain.com; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`; } } });
配置后,关键令牌会以app_id_token、app_access_token这类简洁名称存储,前后端提取都更直观。
内容的提问来源于stack exchange,提问作者Hannesh

