ユーザーステータスFORCE_CHANGE_PASSWORDを変更する方法は?


97

AWS Cognitoを使用して、テスト目的でダミーユーザーを作成したいと思います。

次に、AWSコンソールを使用してそのようなユーザーを作成しますが、ユーザーのステータスはに設定されていFORCE_CHANGE_PASSWORDます。その値では、このユーザーを認証できません。

このステータスを変更する方法はありますか?

UPDATECLIからユーザーを作成するときの同じ動作


1
@joeによって提供されたユーザーの回答
donlys

回答:


15

ご不便をおかけして申し訳ありません。ユーザーを作成して直接認証するだけのワンステッププロセスはありません。管理者がユーザーが直接使用できるパスワードを設定できるようにするなど、将来的にこれを変更する可能性があります。今のところAdminCreateUser、アプリを使用して、またはアプリでユーザーを登録してユーザーを作成する場合は、ログイン時にユーザーにパスワードの変更を強制するか、ユーザーにメールアドレスまたは電話番号を確認してユーザーのステータスをに変更させるなど、追加の手順が必要ですCONFIRMED


4
今のところ、AdminCreateUserを使用するか、アプリでユーザーを登録することによってユーザーを作成する場合、ログイン時にユーザーにパスワードの変更を強制するか、ユーザーにメールアドレスまたは電話番号を確認してユーザーのステータスを次のように変更させるなど、追加の手順が必要です。確認済み。これらの余分なefoortとは正確には何であり、JSSDKからそれらをトリガーするにはどうすればよいですか。
SaurabhTiwari19年

3
@joeは、追加されたため、現在は可能であると指摘しました。--permanentフラグを探します:stackoverflow.com/a/56948249/3165552
isaias-b

149

久しぶりですが、この投稿に出くわした他の人に役立つかもしれないと思いました。

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、その他のチャレンジパラメーター、およびユーザーセッションキーで応答します。次に、2番目のコマンドを実行して、チャレンジレスポンスを発行できます。

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


24
驚くほど役に立ちました。さらに2つのヒント:「クライアントのシークレットハッシュを確認できません」に関するエラーが発生した場合は、シークレットなしで別のアプリクライアントを作成し、それを使用します(stackoverflow.com/questions/37438879/…)。「無効な属性が指定されました。XXXがありません」というエラーが表示された場合は、不足している属性をフォーマットuserAttributes.$FIELD_NAME=$VALUEgithub.com/aws/aws-sdk-js/issues/1290)を使用して渡します。
Lane Rettig 2017

CLIコマンド(この回答を含む)のいずれかを使用してユーザーをFORCE_CHANGE_PASSWORDから抜け出せない場合は、「admin-disable-user」、「admin-enable-user」の順に試すか、コンソールを使用してください。次に、このプロセスを使用するか、通常のパスワードリセットフローを使用できる場合があります。事前定義された制限内でcognitoにログインしなかった場合、ユーザーは「期限切れ」になることがあります。(デフォルトは7日だと思います)
快適な2018年

CLIで試してみましたが、ラムダ内で次のエラーが発生しました:無効な属性が指定され、名前がありません
kolodi 2018年

1
@misherあなたは必要な属性のためにそれを得ています。それらを呼び出しに含めることはできますが、構文は少し奇妙です。--challenge-responses NEW_PASSWORD=password,USERNAME=username,userAttributes.picture=picture,userAttributes.name=name
edzillion19年

88

これはついに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 user1 --password password --permanent

これを使用する前に、以下を使用してAWSCLIを更新する必要がある場合があります。

pip3 install awscli --upgrade


13
これは最新かつ最も効率的なソリューションです!
donlys

7
これが答えになるはずです。
ヤング氏

4
2020年の最良かつ最も簡単なソリューション。ありがとう!
チューダー

23

onSuccess: function (result) { ... },ログイン機能内の後にこのコードを追加するだけです。これで、ユーザーのステータスはCONFIRMEDになります。

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

1
これは私にとってはうまくいきます。パスワードを変更したくない場合は、現在のパスワードを渡すこともできます。
mvandillen

再帰FTW!ありがとう!(再帰がありthis、完全に新しいパスワードのチャレンジに)
ポール・S

22

次のようにユーザーをFORCE_CHANGE_PASSWORD呼び出すことrespondToAuthChallenge()で、そのユーザーステータスを変更できます。

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。であることがコンソールに表示されます。


1
どうやってここに来たのかわかりません。XXXしたセッションを取得するために何を呼び出しましたか?adminInitiateAuthを呼び出すと、UserNotFoundExceptionというエラーが表示されます。
ライアンシリントン

3
その答えが明確でなかったらごめんなさい。詳細は次のとおりです。1。ユーザープールには、生成された秘密鍵なしで作成された「your_own3j63rs8j16bxxxsto25db00obh」というクライアントがあります。クライアントにキーが割り当てられている場合、上記のコードは機能しません。2)セッションキーは、呼び出しによって返される値ですcognitoidentityserviceprovider.adminInitiateAuth({ AuthFlow: 'ADMIN_NO_SRP_AUTH', ClientId: 'your_own3j63rs8j16bxxxsto25db00obh', UserPoolId: 'us-east-1_DtNSUVT7n', AuthParameters: { USERNAME: 'user3', PASSWORD: 'original_password' } }, callback);
Ariel Araza 2017

3)user3コンソールで作成され、最初にパスワードが与えられました'original_password'
Ariel Araza 2017

OK。UserNotFoundExceptionが発生した理由がわかりました。ログインするユーザー名としてエイリアスを使用していたためです。これはJSAPIでは正常に機能しますが、adminInitiateAuthでは機能しないようです。アリエルアラザありがとう、私はあなたの助けに感謝します。
ライアンシリントン

わーい!私はついにこれを機能させました。ありがとうございました!アリエルありがとう!
ライアン

11

あなたがまだこれと戦っているのかどうかはわかりませんが、たくさんのテストユーザーを作成するためだけに、私はその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%
  1. admin-confirm-sign-upを使用してユーザーを確認します
aws cognito-idp admin-confirm-sign-up \
--user-pool-id %aws_user_pools_web_client_id% \
--username %email_address%

5

更新:

私は現在、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.completeNewPasswordChallenge()内で実行されcognitoUser.authenticateUser( ,{newPasswordRequired})ます。

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

@トム-それはあなたのために働きますか?明確にできることはありますか?
qqan.ny 2017

今はずっと良くなっています。
トム・アランダ

@ qqan.nyはpromiseとcallbackを同時に使用しますか?どうして?
iuriiGolskyi18年

@Iurii Golskyi-当時、私はよくわかりませんでした。AWSとJSの両方を最初から学び始めたばかりでした。
qqan.ny 2018

4

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

それがそれらの統合テストに役立つことを願っています(フォーマットについて申し訳ありません)


4

基本的にこれは同じ答えですが、.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
        });
    }

3

コンソールから管理者としてのステータスを変更しようとしている場合。次に、ユーザーを作成した後、以下の手順に従います。

  1. Cognitoでgoto->「manageuserpool」->
  2. [アプリの統合]セクションの[アプリクライアントの設定]に移動します。
  3. 以下の項目を確認してくださいi)Cognitoユーザープールii)認証コードの付与iii)暗黙の付与iv)電話v)メールvi)openid vii)aws.cognito.signin.user.admin viii)プロファイル
  4. アプリケーションのコールバックURLを入力します。よくわからない場合は、たとえばhttps://google.com以降を入力して、実際のコールバックURLに変更できます。
  5. [変更を保存]をクリックします。
  6. 変更が保存されたら、「ホストされたUIの起動」リンクをクリックします
  7. 新しく作成したユーザーの資格情報を入力します
  8. 新しい資格情報でパスワードをリセットし、同じものをユーザーと共有します

ステップ2

ステップ34 5 6

ステップ7

ステップ8


2

私はそれが同じ答えであることを知っていますが、それは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)

        })

    })
}

1

OK。管理者が新しいユーザーを作成できるコードがついにできました。プロセスは次のようになります。

  1. 管理者がユーザーを作成します
  2. ユーザーは一時パスワードが記載されたメールを受け取ります
  3. ユーザーがログインし、パスワードの変更を求められます

ステップ1は難しい部分です。NodeJSでユーザーを作成するための私のコードは次のとおりです。

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

基本的に、電子メールが検証済みと見なされるように強制するには、2番目のコマンドを送信する必要があります。ユーザーは、一時パスワードを取得するために電子メールにアクセスする必要があります(これにより電子メールも検証されます)。ただし、電子メールを確認済みに設定する2回目の呼び出しがないと、パスワードをリセットするための適切な呼び出しが返されません。


それでもメールが届かないのですが、何か提案はありますか?
ヴィニシウス2018

奇妙なことに、SESなどにアクセスできるCognitoでメールアドレスを正しく設定しましたか?Cogntioは、送信しようとしている電子メールアドレスを確認するか、誰かに送信することを承認されるまで、人々に電子メールを送信するだけではありません。
ライアン

確認コードのメールが届きますので、設定は正しいです。一時パスワードが記載された電子メールだけが届くことはありません...電子メールを送信するために、事前サインアップトリガーに添付されたラムダを作成することになりました。
ヴィニシウス2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.