如何更改用户状态 FORCE _ CHOGE _ PASSWORD?

使用 AWS Cognito,我想创建用于测试目的的虚拟用户。

然后使用 AWS 控制台创建这样的用户,但是用户的 地位设置为 FORCE_CHANGE_PASSWORD。使用该值,无法对此用户进行身份验证。

有办法改变这种状态吗?

更新 从 CLI 创建用户时的相同行为

116110 次浏览

对不起,你有困难。我们没有一个只需要创建用户并直接对其进行身份验证的单步流程。将来我们可能会改变这一点,比如允许管理员设置用户可以直接使用的密码。现在,当你使用 AdminCreateUser或者通过注册用户来创建用户时,需要额外的步骤,要么强制用户在登录时更改密码,要么让用户验证电子邮件或电话号码以将用户的状态更改为 CONFIRMED

您可以通过对用户调用 respondToAuthChallenge()来更改该用户状态 FORCE_CHANGE_PASSWORD,如下所示:

var params = {
ChallengeName: 'NEW_PASSWORD_REQUIRED',
ClientId: 'your_own3j6...0obh',
ChallengeResponses: {
USERNAME: 'user3',
NEW_PASSWORD: 'changed12345'
},
Session: 'xxxxxxxxxxZDMcRu-5u...sCvrmZb6tHY'
};


cognitoidentityserviceprovider.respondToAuthChallenge(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else     console.log(data);           // successful response
});

在此之后,您将在控制台中看到 user3状态为 CONFIRMED

我知道已经有一段时间了,但是我想这可能会帮助其他读到这篇文章的人。

您可以使用 AWS CLI 来更改用户密码,但是这是一个多步骤的过程:


步骤1: 为所需用户获取会话令牌:

aws cognito-idp admin-initiate-auth --user-pool-id %USER POOL ID% --client-id %APP CLIENT ID% --auth-flow ADMIN_NO_SRP_AUTH --auth-parameters USERNAME=%USERS USERNAME%,PASSWORD=%USERS CURRENT PASSWORD%

如果返回关于 Unable to verify secret hash for client创建另一个没有秘密的应用程序客户端的错误,请使用该客户端 ID。

步骤2: 如果步骤1成功,它将使用挑战 NEW_PASSWORD_REQUIRED、其他挑战参数和用户会话密钥进行响应。然后,您可以运行第二个命令来发出质疑响应:

aws cognito-idp admin-respond-to-auth-challenge --user-pool-id %USER POOL ID% --client-id %CLIENT ID% --challenge-name NEW_PASSWORD_REQUIRED --challenge-responses NEW_PASSWORD=%DESIRED PASSWORD%,USERNAME=%USERS USERNAME% --session %SESSION KEY FROM PREVIOUS COMMAND with ""%

如果出现关于 Invalid attributes given, XXX is missing的错误,请使用格式 userAttributes.$FIELD_NAME=$VALUE传递缺少的属性

上面的命令应该返回一个有效的身份验证结果和适当的令牌。


重要提示: 为了实现这一点,Cognito 用户池必须有一个配置了 ADMIN_NO_SRP_AUTH功能(第五步: 本文档)的 应用客户端

好的。我终于有了管理员可以创建新用户的代码。过程是这样的:

  1. 管理员创建用户
  2. 用户收到一封带有临时密码的电子邮件
  3. 用户登录并被要求更改他们的密码

步骤1是最难的部分,下面是我在 Node JS 中创建用户的代码:

let params = {
UserPoolId: "@cognito_pool_id@",
Username: username,
DesiredDeliveryMediums: ["EMAIL"],
ForceAliasCreation: false,
UserAttributes: [
{ Name: "given_name", Value: firstName },
{ Name: "family_name", Value: lastName},
{ Name: "name", Value: firstName + " " + lastName},
{ Name: "email", Value: email},
{ Name: "custom:title", Value: title},
{ Name: "custom:company", Value: company + ""}
],
};
let cognitoIdentityServiceProvider = new AWS.CognitoIdentityServiceProvider();
cognitoIdentityServiceProvider.adminCreateUser(params, function(error, data) {
if (error) {
console.log("Error adding user to cognito: " + error, error.stack);
reject(error);
} else {
// Uncomment for interesting but verbose logging...
//console.log("Received back from cognito: " + CommonUtils.stringify(data));
cognitoIdentityServiceProvider.adminUpdateUserAttributes({
UserAttributes: [{
Name: "email_verified",
Value: "true"
}],
UserPoolId: "@cognito_pool_id@",
Username: username
}, function(err) {
if (err) {
console.log(err, err.stack);
} else {
console.log("Success!");
resolve(data);
}
});
}
});

基本上,您需要发送第二个命令来强制电子邮件被认为是经过验证的。用户仍然需要去他们的电子邮件获得临时密码(也验证电子邮件)。但是,如果没有第二个电话,设置电子邮件的验证,你将不会得到正确的电话回来重置他们的密码。

只需在登录函数中的 onSuccess: function (result) { ... },后面添加这段代码,用户就会获得状态 确认

newPasswordRequired: function(userAttributes, requiredAttributes) {
// User was signed up by an admin and must provide new
// password and required attributes, if any, to complete
// authentication.


// the api doesn't accept this field back
delete userAttributes.email_verified;


// unsure about this field, but I don't send this back
delete userAttributes.phone_number_verified;


// Get these details and call
cognitoUser.completeNewPasswordChallenge(newPassword, userAttributes, this);
}

更新:

已经有了一些更新,不再需要 Amplify 客户端。 在 adminCreateUser ()之后,您现在可以只使用

cisp.adminSetUserPassword({
UserPoolId: pool_id,
Username: login,
Password: password,
Permanent: true
})


Https://docs.aws.amazon.com/cognito-user-identity-pools/latest/apireference/api_adminsetuserpassword.html

这将设置用户为“确认”。

更新:

我现在在 NodeJS Lambda 中使用这个,翻译成放大:

// enable node-fetch polyfill for Node.js
global.fetch = require("node-fetch").default;
global.navigator = {};


const AWS = require("aws-sdk");
const cisp = new AWS.CognitoIdentityServiceProvider();


const Amplify = require("@aws-amplify/core").default;
const Auth = require("@aws-amplify/auth").default;


...




/*
this_user: {
given_name: string,
password: string,
email: string,
cell: string
}
*/
const create_cognito = (this_user) => {
let this_defaults = {
password_temp: Math.random().toString(36).slice(-8),
password: this_user.password,
region: global._env === "prod" ? production_region : development_region,
UserPoolId:
global._env === "prod"
? production_user_pool
: development_user_pool,
ClientId:
global._env === "prod"
? production_client_id
: development_client_id,
given_name: this_user.given_name,
email: this_user.email,
cell: this_user.cell,
};


// configure Amplify
Amplify.configure({
Auth: {
region: this_defaults.region,
userPoolId: this_defaults.UserPoolId,
userPoolWebClientId: this_defaults.ClientId,
},
});
if (!Auth.configure())
return Promise.reject("could not configure amplify");


return new Promise((resolve, reject) => {
let _result = {};


let this_account = undefined;
let this_account_details = undefined;


// create cognito account
cisp
.adminCreateUser({
UserPoolId: this_defaults.UserPoolId,
Username: this_defaults.given_name,
DesiredDeliveryMediums: ["EMAIL"],
ForceAliasCreation: false,
MessageAction: "SUPPRESS",
TemporaryPassword: this_defaults.password_temp,
UserAttributes: [
{ Name: "given_name", Value: this_defaults.given_name },
{ Name: "email", Value: this_defaults.email },
{ Name: "phone_number", Value: this_defaults.cell },
{ Name: "email_verified", Value: "true" },
],
})
.promise()
.then((user) => {
console.warn(".. create_cognito: create..");
_result.username = user.User.Username;
_result.temporaryPassword = this_defaults.password_temp;
_result.password = this_defaults.password;


// sign into cognito account
return Auth.signIn(_result.username, _result.temporaryPassword);
})
.then((user) => {
console.warn(".. create_cognito: signin..");


// complete challenge
return Auth.completeNewPassword(user, _result.password, {
email: this_defaults.email,
phone_number: this_defaults.cell,
});
})
.then((user) => {
console.warn(".. create_cognito: confirmed..");
this_account = user;
// get details
return Auth.currentAuthenticatedUser();
})
.then((this_details) => {
if (!(this_details && this_details.attributes))
throw "account creation failes";


this_account_details = Object.assign({}, this_details.attributes);


// signout
return this_account.signOut();
})
.then(() => {
console.warn(".. create_cognito: complete");
resolve(this_account_details);
})
.catch((err) => {
console.error(".. create_cognito: error");
console.error(err);
reject(err);
});
});
};


我正在设置一个临时密码,然后稍后将其重置为用户请求的密码。

老帖子:

您可以使用 amazon-cognito-Identity-js SDK 解决这个问题,方法是在用 cognitoidentityserviceprovider.adminCreateUser()创建帐户之后使用临时密码进行身份验证,并在 cognitoUser.authenticateUser( ,{newPasswordRequired})中运行 cognitoUser.completeNewPasswordChallenge()——所有这些都在创建用户的函数中进行。

我在 AWS lambda 中使用下面的代码来创建启用的 Cognoto 用户帐户。我相信它可以被优化,对我耐心点。这是我的第一篇文章,我对 JavaScript 还是很新。

var AWS = require("aws-sdk");
var AWSCognito = require("amazon-cognito-identity-js");


var params = {
UserPoolId: your_poolId,
Username: your_username,
DesiredDeliveryMediums: ["EMAIL"],
ForceAliasCreation: false,
MessageAction: "SUPPRESS",
TemporaryPassword: your_temporaryPassword,
UserAttributes: [
{ Name: "given_name", Value: your_given_name },
{ Name: "email", Value: your_email },
{ Name: "phone_number", Value: your_phone_number },
{ Name: "email_verified", Value: "true" }
]
};


var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
let promise = new Promise((resolve, reject) => {
cognitoidentityserviceprovider.adminCreateUser(params, function(err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});


promise
.then(data => {
// login as new user and completeNewPasswordChallenge
var anotherPromise = new Promise((resolve, reject) => {
var authenticationDetails = new AWSCognito.AuthenticationDetails({
Username: your_username,
Password: your_temporaryPassword
});
var poolData = {
UserPoolId: your_poolId,
ClientId: your_clientId
};
var userPool = new AWSCognito.CognitoUserPool(poolData);
var userData = {
Username: your_username,
Pool: userPool
};


var cognitoUser = new AWSCognito.CognitoUser(userData);
let finalPromise = new Promise((resolve, reject) => {
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function(authResult) {
cognitoUser.getSession(function(err) {
if (err) {
} else {
cognitoUser.getUserAttributes(function(
err,
attResult
) {
if (err) {
} else {
resolve(authResult);
}
});
}
});
},
onFailure: function(err) {
reject(err);
},
newPasswordRequired(userAttributes, []) {
delete userAttributes.email_verified;
cognitoUser.completeNewPasswordChallenge(
your_newPoassword,
userAttributes,
this
);
}
});
});


finalPromise
.then(finalResult => {
// signout
cognitoUser.signOut();
// further action, e.g. email to new user
resolve(finalResult);
})
.catch(err => {
reject(err);
});
});
return anotherPromise;
})
.then(() => {
resolve(finalResult);
})
.catch(err => {
reject({ statusCode: 406, error: err });
});

对于 Java SDK,假设您的 Cognito 客户端已经设置好,并且您的用户处于 FORCE _ CHOGE _ PASSWORD 状态,那么您可以执行以下操作来获得用户 CONFIRMED... 然后按照正常方式进行授权。

AdminCreateUserResult createUserResult = COGNITO_CLIENT.adminCreateUser(createUserRequest());


AdminInitiateAuthResult authResult = COGNITO_CLIENT.adminInitiateAuth(authUserRequest());




Map<String,String> challengeResponses = new HashMap<>();
challengeResponses.put("USERNAME", USERNAME);
challengeResponses.put("NEW_PASSWORD", PASSWORD);
RespondToAuthChallengeRequest respondToAuthChallengeRequest = new RespondToAuthChallengeRequest()
.withChallengeName("NEW_PASSWORD_REQUIRED")
.withClientId(CLIENT_ID)
.withChallengeResponses(challengeResponses)
.withSession(authResult.getSession());


COGNITO_CLIENT.respondToAuthChallenge(respondToAuthChallengeRequest);

希望它对那些集成测试有所帮助(关于格式的问题很抱歉)

不知道您是否还在纠结这个问题,但是为了创建一些测试用户,我使用了 awscli:

  1. 使用 conito-idp 中的 sign-up 子命令创建用户
aws cognito-idp sign-up \
--region %aws_project_region% \
--client-id %aws_user_pools_web_client_id% \
--username %email_address% \
--password %password% \
--user-attributes Name=email,Value=%email_address%
  1. 使用管理-确认-注册确认用户
aws cognito-idp admin-confirm-sign-up \
--user-pool-id %aws_user_pools_web_client_id% \
--username %email_address%

基本上这是相同的答案,但是对于.Net C # SDK:

下面将使用所需的用户名和密码创建完整的管理用户。 具有以下用户模式:

public class User
{
public string Username { get; set; }
public string Password { get; set; }
}

您可以创建一个用户,并使其准备好使用:

   public void AddUser(User user)
{
var tempPassword = "ANY";
var request = new AdminCreateUserRequest()
{
Username = user.Username,
UserPoolId = "MyuserPoolId",
TemporaryPassword = tempPassword
};
var result = _cognitoClient.AdminCreateUserAsync(request).Result;
var authResponse = _cognitoClient.AdminInitiateAuthAsync(new AdminInitiateAuthRequest()
{
UserPoolId = "MyuserPoolId",
ClientId = "MyClientId",
AuthFlow = AuthFlowType.ADMIN_NO_SRP_AUTH,
AuthParameters = new Dictionary<string, string>()
{
{"USERNAME",user.Username },
{"PASSWORD", tempPassword}
}
}).Result;
_cognitoClient.RespondToAuthChallengeAsync(new RespondToAuthChallengeRequest()
{
ClientId = "MyClientId",
ChallengeName = ChallengeNameType.NEW_PASSWORD_REQUIRED,
ChallengeResponses = new Dictionary<string, string>()
{
{"USERNAME",user.Username },
{"NEW_PASSWORD",user.Password }
},
Session = authResponse.Session
});
}

我知道这是相同的答案,但认为它可能有助于 Go开发社区。基本上它是启动认证请求,得到会话和响应的挑战 NEW_PASSWORD_REQUIRED

func sessionWithDefaultRegion(region string) *session.Session {
sess := Session.Copy()
if v := aws.StringValue(sess.Config.Region); len(v) == 0 {
sess.Config.Region = aws.String(region)
}


return sess
}






func (c *CognitoAppClient) ChangePassword(userName, currentPassword, newPassword string)   error {


sess := sessionWithDefaultRegion(c.Region)
svc := cognitoidentityprovider.New(sess)


auth, err := svc.AdminInitiateAuth(&cognitoidentityprovider.AdminInitiateAuthInput{
UserPoolId:aws.String(c.UserPoolID),
ClientId:aws.String(c.ClientID),
AuthFlow:aws.String("ADMIN_NO_SRP_AUTH"),
AuthParameters: map[string]*string{
"USERNAME": aws.String(userName),
"PASSWORD": aws.String(currentPassword),
},


})






if err != nil {
return err
}


request := &cognitoidentityprovider.AdminRespondToAuthChallengeInput{
ChallengeName: aws.String("NEW_PASSWORD_REQUIRED"),
ClientId:aws.String(c.ClientID),
UserPoolId: aws.String(c.UserPoolID),
ChallengeResponses:map[string]*string{
"USERNAME":aws.String(userName),
"NEW_PASSWORD": aws.String(newPassword),
},
Session:auth.Session,
}




_, err = svc.AdminRespondToAuthChallenge(request)


return err
}

下面是一个单元测试:

import (
"fmt"
"github.com/aws/aws-sdk-go/service/cognitoidentityprovider"
. "github.com/smartystreets/goconvey/convey"
"testing"
)




func TestCognitoAppClient_ChangePassword(t *testing.T) {




Convey("Testing ChangePassword!", t, func() {
err := client.ChangePassword("user_name_here", "current_pass", "new_pass")






Convey("Testing ChangePassword Results!", func() {
So(err, ShouldBeNil)


})


})
}

这最终被添加到 AWSCLI: https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/admin-set-user-password.html

您可以使用以下方法更改用户密码和更新状态:

aws cognito-idp admin-set-user-password \
--user-pool-id <your-user-pool-id> \
--username <username> \
--password <password> \
--permanent

在使用之前,您可能需要使用以下方法更新您的 AWS CLI:

pip3 install awscli --upgrade

如果您试图从控制台更改管理员的状态。然后在创建用户后按照以下步骤操作。

  1. 在 Cognito goto-> “ management user pool”->
  2. 应用程序集成部分下的“应用程序客户端设置”。
  3. 检查下列项目 I)认知用户池 ii)授权码授予 iii)隐式授予 iv)电话 v)电子邮件 vi) openid viii) aws.Cognito.signin.User.admin viii)配置文件
  4. 输入应用程序的回调 URL。如果您不确定输入例如: https://google.com,稍后您可以将其更改为您的实际回调 URL
  5. 点击保存更改。
  6. 保存更改后,单击“ Launch Hosted UI”链接
  7. 输入新创建用户的凭据
  8. 用新凭据重置密码并将其共享给用户

第二步

步骤3456

步骤7

步骤8

我也经历过很多次同样的情况。因此,我们用 golang 编写了一个小 CLI,它可以作为用户(为了进一步的测试目的)进行身份验证,也可以只是管理性地重置通行证。

那么你作为命令运行的就是

$ > go-cognito-authy --profile cloudy -region eu-central-1 admin reset-pass --username rafpe --pass-new 'Password.0ne2!' --clientID 2jxxxiuui123 --userPoolID  eu-central-1_CWNnTiR0j --session "bCqSkLeoJR_ys...."

解决方案可在 github https://github.com/RafPe/go-cognito-authy/tree/master上获得

如果您的应用程序有一个宿主用户界面,那么您也可以使用 Cognoto 的宿主用户界面。只要用所需的用户登录,就会提示您更改密码。在此之后,用户状态被确认,您可以正常进行。