使用amazon-cognito-identity-js实现Cognito登录与刷新token接口报错如何解决
Amazon Cognito 登录与刷新Token后端实现方案
报错核心原因
你遇到的NotAuthorizedException: Invalid Refresh Token报错,核心问题有两个:
refreshToken方法中硬编码了用户名lacucudi,只有刷新该用户的token时才可能匹配,其他用户、或者用户名大小写不匹配时都会校验失败- 如果你的Cognito用户池应用客户端开启了「生成客户端密钥」,
amazon-cognito-identity-js库无法自动处理密钥哈希,也会触发refresh token校验失败
正确实现代码
第一步:抽离公共配置
避免重复初始化用户池实例,敏感配置建议放到环境变量中存储:
import { AuthenticationDetails, CognitoUser, CognitoUserPool, CognitoRefreshToken } from "amazon-cognito-identity-js" // 配置信息建议从环境变量读取,不要硬编码在业务代码中 const COGNITO_CONFIG = { UserPoolId: process.env.COGNITO_USER_POOL_ID || 'eu-north-1_xxxxxx', ClientId: process.env.COGNITO_CLIENT_ID || '3al0l3mhcxxxxxqgnp789987' } // 全局复用用户池实例 const userPool = new CognitoUserPool(COGNITO_CONFIG)
第二步:登录接口实现
封装为Promise形式,方便后端路由层调用返回响应:
/** * 用户名密码登录 * @param username 用户名 * @param password 密码 * @returns token集合 */ public async loginWithAmazonCognitoIdentity (username: string, password: string): Promise<{ accessToken: string, idToken: string, refreshToken: string, expireIn: number }> { const authenticationDetails = new AuthenticationDetails({ Username: username, Password: password }) const cognitoUser = new CognitoUser({ Username: username, Pool: userPool }) return new Promise((resolve, reject) => { cognitoUser.authenticateUser(authenticationDetails, { onSuccess: (result) => { resolve({ accessToken: result.getAccessToken().getJwtToken(), idToken: result.getIdToken().getJwtToken(), refreshToken: result.getRefreshToken().getToken(), expireIn: result.getAccessToken().getExpiration() }) }, onFailure: (err) => { reject(err) } }) }) }
第三步:刷新Token接口实现
必须传入用户名和refreshToken两个参数,不能硬编码用户名:
/** * 刷新Access Token * @param username 对应用户的用户名(需和登录时传入的完全一致,包含大小写) * @param refreshToken 登录时获取的refresh token * @returns 新的token集合 */ public async refreshToken(username: string, refreshToken: string): Promise<{ accessToken: string, idToken: string, refreshToken: string, expireIn: number }> { const cognitoUser = new CognitoUser({ Username: username, Pool: userPool }) const refreshTokenInstance = new CognitoRefreshToken({ RefreshToken: refreshToken }) return new Promise((resolve, reject) => { cognitoUser.refreshSession(refreshTokenInstance, (err, session) => { if (err) return reject(err) resolve({ accessToken: session.getAccessToken().getJwtToken(), idToken: session.getIdToken().getJwtToken(), refreshToken: session.getRefreshToken().getToken(), expireIn: session.getAccessToken().getExpiration() }) }) }) }
注意事项
- 创建Cognito用户池应用客户端时不要勾选「生成客户端密钥」,
amazon-cognito-identity-js仅支持无密钥的客户端场景 - 刷新token时传入的用户名必须和登录时的用户名完全一致,包含大小写
- 用户被禁用、修改密码、refresh token超过有效期时,都会触发Invalid Refresh Token报错,可在Cognito用户池控制台的「应用客户端设置」中调整refresh token的有效期,最长支持10年
- 若开启了用户池的设备跟踪功能,需要在登录时保存设备Key,刷新时传入设备信息,否则也会校验失败
内容的提问来源于stack exchange,提问作者C1X
相关产品推荐
相关产品推荐

