NestJS集成Cognito调用ChangePassword时报用户名与用户池信息缺失错误
问题排查与解决方案
错误核心原因
- 异步流程处理错误:你的
changePassword方法未返回Promise,内部使用回调式API导致函数直接返回undefined,同时回调中抛出的错误无法被Controller层的try/catch捕获。 - 会话初始化问题:
cognitoUser.getSession()依赖客户端本地存储的Cognito会话信息(如localStorage中的会话数据),但你的场景是通过API传递用户名/密码修改密码,未在服务端维护该会话,导致getSession调用失败,最终触发"Username and Pool information are required."错误。
修正方案
方案1:包装回调API为Promise,手动传入会话信息
如果需要保留前端传递的会话凭证,可从请求头获取登录后的Token,手动初始化CognitoUser会话:
// Service代码 async changePassword(@Req() req, user: ChangePasswordDto) { const { username, oldPassword, newPassword } = user; // 从请求头获取Bearer Token const authToken = req.headers.authorization?.split(' ')[1]; if (!authToken) { throw new HttpException('缺少认证凭证', HttpStatus.UNAUTHORIZED); } const userData = { Username: username, Pool: this.userPool, }; const cognitoUser = new CognitoUser(userData); // 手动设置会话 const userSession = new CognitoUserSession({ IdToken: new CognitoIdToken({ IdToken: authToken }), }); cognitoUser.setSignInUserSession(userSession); // 包装changePassword为Promise return new Promise((resolve, reject) => { cognitoUser.changePassword(oldPassword, newPassword, (err, result) => { if (err) { reject(new HttpException(err.message, HttpStatus.BAD_REQUEST)); } else { resolve({ message: '密码修改成功' }); } }); }); }
方案2:使用AWS SDK服务端API(推荐)
直接使用AWS官方SDK的AdminChangePasswordCommand,无需依赖客户端会话,只需服务端IAM角色具备cognito-idp:AdminChangePassword权限:
// 先导入AWS SDK依赖 import { CognitoIdentityProviderClient, AdminChangePasswordCommand } from "@aws-sdk/client-cognito-identity-provider"; // Service类中初始化客户端 private cognitoClient: CognitoIdentityProviderClient; constructor(private authConfig: AuthConfig) { this.userPool = new CognitoUserPool({ UserPoolId: this.authConfig.userPoolId, ClientId: this.authConfig.clientId, }); this.cognitoClient = new CognitoIdentityProviderClient({ region: this.authConfig.region, // 填写你的AWS区域,如us-east-1 }); } async changePassword(user: ChangePasswordDto) { const { username, oldPassword, newPassword } = user; const command = new AdminChangePasswordCommand({ UserPoolId: this.authConfig.userPoolId, Username: username, PreviousPassword: oldPassword, ProposedPassword: newPassword, }); try { await this.cognitoClient.send(command); return { message: '密码修改成功' }; } catch (err) { throw new HttpException(err.message, HttpStatus.BAD_REQUEST); } }
额外注意事项
- 使用
AdminChangePasswordCommand时,确保目标用户已完成邮箱/手机号验证,否则会触发验证未完成的错误。 - 服务端IAM角色需配置对应权限策略,允许调用
cognito-idp:AdminChangePassword操作。
内容的提问来源于stack exchange,提问作者CandleCoder
相关产品推荐
相关产品推荐

