如何修改用户状态FORCE_CHANGE_PASSWORD



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

然后使用AWS控制台创建这样的用户,但是用户的状态设置为FORCE_CHANGE_PASSWORD。该值表示该用户不能被认证。

有办法改变这个状态吗?

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

这最终被添加到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

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


您可以使用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功能的应用程序客户端(本文档中的步骤5)。

您可以通过在用户上调用 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

只需在登录函数的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);
}

很抱歉您遇到了麻烦。我们没有一步到位的流程,您可以直接创建用户并对其进行身份验证。我们将来可能会对此进行更改,例如允许管理员设置用户可以直接使用的密码。目前,当您使用AdminCreateUser或通过应用程序注册用户创建用户时,需要额外的步骤,要么强制用户在登录时更改密码,要么让用户验证电子邮件或电话号码以将用户状态更改为CONFIRMED .

不确定您是否仍在与此作战斗,但仅用于创建一堆测试用户,我使用awscli如下:

  1. 使用cognito-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%
  • 使用admin-confirm-sign-up确认用户
  • aws cognito-idp admin-confirm-sign-up 
    --user-pool-id %aws_user_pools_web_client_id% 
    --username %email_address%
    

    UPDATE:

    有一些更新,不再需要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- cognitto -identity-js SDK解决这个问题,方法是在使用cognitoidentityserviceprovider.adminCreateUser()创建帐户后使用临时密码进行身份验证,并在cognitoUser.authenticateUser( ,{newPasswordRequired})中运行cognitoUser.completeNewPasswordChallenge()—所有这些都在创建用户的函数中。

    我在AWS lambda中使用以下代码来创建启用的Cognito用户帐户。我相信它可以优化,对我有耐心。这是我的第一篇文章,我对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 });
        });
    

    如果您试图从控制台更改作为管理员的状态。创建用户后,执行以下步骤:

    1. 在Cognito中go -> "manage user pool" ->
    2. 进入应用集成部分的"应用客户端设置"。
    3. 检查以下项目i) Cognito用户池ii)授权码授予iii)隐式授予iv)电话v)电子邮件vi) openid vii) aws. Cognito . signing . User .admin viii)配置文件
    4. 输入应用程序的回调url。如果你不确定,输入例如:https://google.com,然后你可以把它改成你实际的回调url
    5. 点击保存更改
    6. 一旦更改保存,点击链接"启动托管UI"
    7. 输入新创建用户的凭据
    8. 用新凭据重置密码并将其共享给用户
    步骤2

    步骤3 4 5 6

    第7步

    步骤8

    对于Java SDK,假设您的Cognito客户端已经设置,并且您的用户处于FORCE_CHANGE_PASSWORD状态,您可以执行以下操作来确认您的用户…然后像正常人一样认证。

    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);
    

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

    基本上这是相同的答案,但对于。net c# SDK:

    下面的代码将创建一个完整的admin用户,包含所需的用户名和密码。具有以下用户模型:

    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
            });
        }
    

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

      Admin创建用户
    1. 用户收到带有临时密码的电子邮件
    2. 用户登录并被要求更改密码

    步骤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);
          }
        });
      }
    });
    

    基本上,您需要发送第二个命令来强制将电子邮件视为已验证。用户仍然需要访问他们的电子邮件以获取临时密码(这也验证了电子邮件)。但如果没有第二次电话将电子邮件设置为验证,你就不会得到正确的电话来重置他们的密码。

    我知道这是相同的答案,但认为它可能有助于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)
            })
        })
    }
    

    我曾多次遇到同样的情况。因此,用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

    如果您的应用程序有一个,您也可以使用Cognito的托管UI。只需以所需的用户登录,您将被提示更改密码。在确认用户状态之后,您可以正常进行操作。

    相关内容

    • 没有找到相关文章

    最新更新