Wie ändere ich den Benutzerstatus FORCE_CHANGE_PASSWORD?

89

Mit AWS Cognito möchte ich Dummy-Benutzer zu Testzwecken erstellen.

Ich verwende dann die AWS-Konsole , um einen solchen Benutzer zu erstellen, aber der Status des Benutzers ist festgelegt FORCE_CHANGE_PASSWORD. Mit diesem Wert kann dieser Benutzer nicht authentifiziert werden.

Gibt es eine Möglichkeit, diesen Status zu ändern?

UPDATE Gleiches Verhalten beim Erstellen eines Benutzers über die CLI

Dominique Fläschchen
quelle
1
Benutzerantwort von @joe
donlys

Antworten:

15

Entschuldigung, Sie haben Schwierigkeiten. Wir haben keinen einstufigen Prozess, bei dem Sie einfach Benutzer erstellen und direkt authentifizieren können. Möglicherweise ändern wir dies in Zukunft, damit Administratoren Kennwörter festlegen können, die von Benutzern direkt verwendet werden können. Wenn Sie Benutzer erstellen, die Benutzer entweder AdminCreateUsermit der App verwenden oder sich bei der App anmelden, sind zusätzliche Schritte erforderlich, die entweder dazu führen, dass Benutzer das Kennwort bei der Anmeldung ändern müssen, oder dass Benutzer die E-Mail- oder Telefonnummer überprüfen, um den Status des Benutzers in zu ändern CONFIRMED.

Ionut Trestian
quelle
4
Wenn Sie Benutzer entweder mit AdminCreateUser erstellen oder Benutzer mit der App anmelden, sind zusätzliche Schritte erforderlich, die Benutzer entweder dazu zwingen, das Kennwort bei der Anmeldung zu ändern, oder Benutzer die E-Mail- oder Telefonnummer überprüfen lassen, um den Status des Benutzers zu ändern BESTÄTIGT. Was genau sind diese zusätzlichen Anstrengungen und wie kann ich sie über das JS SDK auslösen?
Saurabh Tiwari
1
@ Joe wies darauf hin, dass es jetzt möglich ist, da es hinzugefügt wurde. Suchen--permanent
Sie
144

Ich weiß, dass es eine Weile her ist, dachte aber, dass dies anderen Menschen helfen könnte, die auf diesen Beitrag stoßen.

Sie können die AWS-CLI verwenden, um das Benutzerkennwort zu ändern. Dies ist jedoch ein mehrstufiger Prozess:


Schritt 1: Holen Sie sich ein Sitzungstoken für den gewünschten Benutzer:

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%

Wenn dies einen Fehler zurückgibt Unable to verify secret hash for client, erstellen Sie einen anderen App-Client ohne Geheimnis und verwenden Sie diese Client-ID.

Schritt 2: Wenn Schritt 1 erfolgreich ist, antwortet er mit der Herausforderung NEW_PASSWORD_REQUIRED, anderen Herausforderungsparametern und dem Sitzungsschlüssel des Benutzers. Anschließend können Sie den zweiten Befehl ausführen, um die Challenge-Antwort auszugeben:

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 ""%

Wenn Sie eine Fehlermeldung erhalten, Invalid attributes given, XXX is missingübergeben Sie die fehlenden Attribute im FormatuserAttributes.$FIELD_NAME=$VALUE

Der obige Befehl sollte ein gültiges Authentifizierungsergebnis und entsprechende Token zurückgeben.


Wichtig: Damit dies funktioniert, MUSS im Cognito-Benutzerpool ein App-Client mit ADMIN_NO_SRP_AUTHFunktionalität konfiguriert sein ( Schritt 5 in diesem Dokument ).

Neutraler Pinguin
quelle
24
Erstaunlich hilfreich. Zwei weitere Tipps: Wenn Sie die Fehlermeldung "Geheime Hash für Client können nicht überprüft werden" erhalten, erstellen Sie einen anderen App-Client ohne Geheimnis und verwenden Sie diesen ( stackoverflow.com/questions/37438879/… ). Wenn Sie die Fehlermeldung "Ungültige Attribute angegeben, XXX fehlt" erhalten, übergeben Sie die fehlenden Attribute im Format userAttributes.$FIELD_NAME=$VALUE( github.com/aws/aws-sdk-js/issues/1290 ).
Lane Rettig
Wenn Sie Ihren Benutzer mit einem der CLI-Befehle (einschließlich dieser Antwort) nicht aus FORCE_CHANGE_PASSWORD herausholen können, versuchen Sie 'admin-disable-user' und dann 'admin-enable-user' oder verwenden Sie die Konsole. Verwenden Sie dann entweder diesen Vorgang, oder verwenden Sie möglicherweise den normalen Ablauf zum Zurücksetzen des Kennworts. Manchmal läuft ein Benutzer ab, wenn er sich nicht innerhalb des vordefinierten Grenzwerts bei cognito angemeldet hat. (Standard 7 Tage denke ich)
comfytoday
Versuchte es mit CLI und in einem Lambda, bekam diesen Fehler: Ungültige Attribute angegeben, Name fehlt
Kolodi
1
@misher Sie erhalten das aufgrund der erforderlichen Attribute. Sie können sie in den Aufruf aufnehmen, aber die Syntax ist etwas seltsam:--challenge-responses NEW_PASSWORD=password,USERNAME=username,userAttributes.picture=picture,userAttributes.name=name
Edzillion
62

Dies wurde schließlich zu AWSCLI hinzugefügt: https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/admin-set-user-password.html

Sie können das Passwort eines Benutzers ändern und den Status aktualisieren, indem Sie:

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

Bevor Sie dies verwenden, müssen Sie möglicherweise Ihre AWS-CLI mithilfe folgender Informationen aktualisieren:

pip3 install awscli --upgrade

Joe
quelle
9
Dies ist die neueste und effizienteste Lösung!
Donlys
4
Dies sollte die Antwort sein.
Mr. Young
1
Beste und einfachste Lösung im Jahr 2020. Danke!
Tudor
23

Fügen Sie diesen Code einfach nach onSuccess: function (result) { ... },Ihrer Anmeldefunktion hinzu. Ihr Benutzer hat dann den Status BESTÄTIGT .

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);
}
In der Hälfte gebacken
quelle
1
Das funktioniert bei mir. Sie können das aktuelle Passwort sogar übergeben, wenn Sie es nicht ändern möchten.
Mvandillen
Rekursion FTW! Vielen Dank! (Rekursion ist die thisauf der komplett neuen Passwort-Herausforderung)
Paul S
22

Sie können diesen Benutzerstatus ändern, FORCE_CHANGE_PASSWORDindem Sie respondToAuthChallenge()den Benutzer wie folgt aufrufen :

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

Danach sehen Sie in der Konsole den user3Status CONFIRMED.

Ariel Araza
quelle
1
Ich verstehe nicht, wie du hierher gekommen bist. Wie haben Sie angerufen, um die Sitzung zu erhalten, die Sie XXX beendet haben? Wenn ich adminInitiateAuth aufrufe, wird die Fehlermeldung UserNotFoundException angezeigt.
Ryan Shillington
3
Entschuldigung, wenn diese Antwort nicht kristallklar war. Weitere Details: 1. Der Benutzerpool verfügt über einen Client mit dem Namen "your_own3j63rs8j16bxxxsto25db00obh", der OHNE einen generierten geheimen Schlüssel erstellt wird. Der obige Code funktioniert nicht, wenn dem Client ein Schlüssel zugewiesen wurde. 2) Sitzungsschlüssel ist der Wert, der durch Aufrufen zurückgegeben wirdcognitoidentityserviceprovider.adminInitiateAuth({ AuthFlow: 'ADMIN_NO_SRP_AUTH', ClientId: 'your_own3j63rs8j16bxxxsto25db00obh', UserPoolId: 'us-east-1_DtNSUVT7n', AuthParameters: { USERNAME: 'user3', PASSWORD: 'original_password' } }, callback);
Ariel Araza
3) user3wurde in der Konsole erstellt und zunächst das Passwort gegeben'original_password'
Ariel Araza
OK. Ich verstehe jetzt, warum ich eine UserNotFoundException bekommen habe. Das lag daran, dass ich einen Alias ​​als Benutzernamen für die Anmeldung verwendet habe, was in der JS-API gut funktioniert, aber anscheinend nicht mit adminInitiateAuth funktioniert. Vielen Dank, Ariel Araza, ich schätze Ihre Hilfe.
Ryan Shillington
Yay! Ich habe es endlich geschafft. Danke dir! Danke Ariel!
Ryan Shillington
10

Ich bin mir nicht sicher, ob Sie immer noch damit kämpfen, aber um nur eine Reihe von Testbenutzern zu erstellen, habe ich Folgendes verwendet awscli:

  1. Verwenden Sie den Unterbefehl zum Anmelden von cognito-idp, um den Benutzer zu erstellen
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. Bestätigen Sie den Benutzer mit admin-verify-sign-up
aws cognito-idp admin-confirm-sign-up \
--user-pool-id %aws_user_pools_web_client_id% \
--username %email_address%
Björn W.
quelle
5

Sie können dies mit dem SDK amazon-cognito-identity-js lösen, indem Sie sich nach der Kontoerstellung mit dem temporären Kennwort authentifizieren cognitoidentityserviceprovider.adminCreateUser()und cognitoUser.completeNewPasswordChallenge()innerhalb von ausführen cognitoUser.authenticateUser( ,{newPasswordRequired})- alles innerhalb der Funktion, die Ihren Benutzer erstellt.

Ich verwende den folgenden Code in AWS Lambda, um aktivierte Cognito-Benutzerkonten zu erstellen. Ich bin sicher, es kann optimiert werden, seien Sie geduldig mit mir. Dies ist mein erster Beitrag und ich bin noch ziemlich neu in 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
quelle
@ Tom - funktioniert es bei dir? Was kann ich klären?
qqan.ny
Viel besser jetzt.
Tom Aranda
@ qqan.ny Versprechen und Rückrufe gleichzeitig nutzen? Warum?
Iurii Golskyi
@Iurii Golskyi - damals wusste ich es nicht besser, hatte gerade angefangen, AWS und JS von Grund auf zu lernen.
qqan.ny
4

Wenn Sie für Java SDK davon ausgehen, dass Ihr Cognito-Client eingerichtet ist und sich Ihr Benutzer im Status FORCE_CHANGE_PASSWORD befindet, können Sie Folgendes tun, um Ihren Benutzer BESTÄTIGT zu erhalten ... und dann wie gewohnt zu authentifizieren.

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

Hoffe, es hilft bei diesen Integrationstests (Entschuldigung für die Formatierung)

HKalsi
quelle
4

Grundsätzlich ist dies die gleiche Antwort, jedoch für .Net C # SDK:

Im Folgenden wird eine vollständige Erstellung des Administratorbenutzers mit dem gewünschten Benutzernamen und Kennwort durchgeführt. Mit dem folgenden Benutzermodell:

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

Sie können einen Benutzer erstellen und ihn gebrauchsfertig machen, indem Sie:

   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
        });
    }
Yahya Hussein
quelle
3

Wenn Sie versuchen, den Status als Administrator über die Konsole zu ändern. Führen Sie dann nach dem Erstellen des Benutzers die folgenden Schritte aus.

  1. In Cognito gehe zu -> "Benutzerpool verwalten" ->
  2. Gehen Sie im Abschnitt "App-Integration" zu "App-Client-Einstellungen".
  3. Überprüfen Sie die folgenden Punkte: i) Cognito-Benutzerpool ii) Autorisierungscode-Erteilung iii) Implizite Erteilung iv) Telefon v) E-Mail vi) openid vii) aws.cognito.signin.user.admin viii) Profil
  4. Geben Sie die Rückruf-URL Ihrer Anwendung ein. Wenn Sie sich nicht sicher sind, geben Sie beispielsweise Folgendes ein : https://google.com und höher. Sie können es in Ihre tatsächliche Rückruf-URL ändern
  5. Klicken Sie auf Änderungen speichern.
  6. Sobald die Änderungen gespeichert sind, klicken Sie auf den Link "Hosted UI starten".
  7. Geben Sie die Anmeldeinformationen des neu erstellten Benutzers ein
  8. Setzen Sie das Kennwort mit neuen Anmeldeinformationen zurück und teilen Sie es dem Benutzer mit

Schritt 2

Schritt 3 4 5 6

Schritt 7

Schritt 8

Rahil BR
quelle
2

Ich weiß, dass es die gleiche Antwort ist, dachte aber, es könnte der GoEntwicklergemeinschaft helfen . Im Grunde geht es darum, eine Authentifizierungsanforderung zu initiieren, die Sitzung abzurufen und auf die Herausforderung zu antwortenNEW_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 
}

Hier ist ein Unit-Test:

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)

        })

    })
}
Muhammad Soliman
quelle
1

OK. Ich habe endlich Code, mit dem ein Administrator einen neuen Benutzer erstellen kann. Der Prozess läuft folgendermaßen ab:

  1. Der Administrator erstellt den Benutzer
  2. Der Benutzer erhält eine E-Mail mit seinem temporären Passwort
  3. Der Benutzer meldet sich an und wird aufgefordert, sein Kennwort zu ändern

Schritt 1 ist der schwierige Teil. Hier ist mein Code zum Erstellen eines Benutzers in 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);
      }
    });
  }
});

Grundsätzlich müssen Sie einen zweiten Befehl senden, um zu erzwingen, dass die E-Mail als verifiziert betrachtet wird. Der Benutzer muss weiterhin zu seiner E-Mail gehen, um das temporäre Kennwort zu erhalten (das auch die E-Mail überprüft). Ohne diesen zweiten Anruf, bei dem die E-Mail auf "Verifiziert" gesetzt wird, erhalten Sie nicht den richtigen Rückruf, um das Kennwort zurückzusetzen.

Ryan Shillington
quelle
Ich erhalte die E-Mail immer noch nicht, ein Vorschlag?
Vinicius
Seltsam, haben Sie die E-Mail-Adresse in Cognito korrekt eingerichtet, mit Zugriff auf SES usw.? Cogntio sendet E-Mails erst dann an andere Personen, wenn Sie entweder die E-Mail-Adresse überprüft haben, an die Sie senden möchten, oder wenn Sie die Genehmigung zum Senden an andere Personen erhalten haben.
Ryan Shillington
Ich erhalte Bestätigungscode-E-Mails, damit die Einstellungen korrekt sind. Nur die E-Mail mit dem temporären Passwort kommt nie ... Am Ende habe ich ein Lambda erstellt, das an den Auslöser vor der Anmeldung angehängt ist, um die E-Mail zu senden.
Vinicius