From c072bac9eeb52e9928da793e6fd64c69e8d6fa30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Schmitt?= Date: Fri, 18 Aug 2023 21:37:01 +0100 Subject: [PATCH] CognitoIDP: user status FORCE_CHANGE_PASSWORD in USER_SRP_AUTH should require new password (#6698) --- moto/cognitoidp/models.py | 9 ++++ tests/test_cognitoidp/test_cognitoidp.py | 60 ++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/moto/cognitoidp/models.py b/moto/cognitoidp/models.py index 4772fd3eb..b9b6d53f6 100644 --- a/moto/cognitoidp/models.py +++ b/moto/cognitoidp/models.py @@ -1525,6 +1525,15 @@ class CognitoIdpBackend(BaseBackend): "ChallengeParameters": {}, } + if user.status == UserStatus.FORCE_CHANGE_PASSWORD: + return { + "ChallengeName": "NEW_PASSWORD_REQUIRED", + "ChallengeParameters": { + "USERNAME": username, + }, + "Session": session, + } + del self.sessions[session] return self._log_user_in(user_pool, client, username) elif challenge_name == "SOFTWARE_TOKEN_MFA": diff --git a/tests/test_cognitoidp/test_cognitoidp.py b/tests/test_cognitoidp/test_cognitoidp.py index 0d8d44951..10397884f 100644 --- a/tests/test_cognitoidp/test_cognitoidp.py +++ b/tests/test_cognitoidp/test_cognitoidp.py @@ -593,6 +593,66 @@ def test_list_user_pools(): assert result["UserPools"][0]["Name"] == name +@mock_cognitoidp +def test_authorize_user_with_force_password_change_status(): + conn = boto3.client("cognito-idp", "us-west-2") + pool_id = conn.create_user_pool(PoolName="TestUserPool")["UserPool"]["Id"] + client_id = conn.create_user_pool_client( + UserPoolId=pool_id, ClientName="TestAppClient" + )["UserPoolClient"]["ClientId"] + + username = "test@example.com" + temp_password = "Tempor@ryPassword123" + new_password = "NewP@ssword456" + conn.admin_create_user( + UserPoolId=pool_id, + Username=username, + TemporaryPassword=temp_password, + ) + + # Initiate USER_SRP_AUTH flow + key = bytes(str(temp_password).encode("latin-1")) + msg = bytes(str(username + client_id).encode("latin-1")) + new_digest = hmac.new(key, msg, hashlib.sha256).digest() + secret_hash = base64.b64encode(new_digest).decode() + result = conn.initiate_auth( + ClientId=client_id, + AuthFlow="USER_SRP_AUTH", + AuthParameters={ + "USERNAME": username, + "SRP_A": uuid.uuid4().hex, + "SECRET_HASH": secret_hash, + }, + ) + + # Try to log in with user in status FORCE_CHANGE_PASSWORD + result = conn.respond_to_auth_challenge( + ClientId=client_id, + ChallengeName=result["ChallengeName"], + ChallengeResponses={ + "PASSWORD_CLAIM_SIGNATURE": str(uuid.uuid4()), + "PASSWORD_CLAIM_SECRET_BLOCK": result["Session"], + "TIMESTAMP": str(uuid.uuid4()), + "USERNAME": username, + }, + ) + assert result["ChallengeName"] == "NEW_PASSWORD_REQUIRED" + assert result["Session"] is not None + assert result["ChallengeParameters"]["USERNAME"] == username + + # Sets a new password to the user and log it in + result = conn.respond_to_auth_challenge( + ClientId=client_id, + ChallengeName="NEW_PASSWORD_REQUIRED", + Session=result["Session"], + ChallengeResponses={ + "USERNAME": username, + "NEW_PASSWORD": new_password, + }, + ) + assert result["AuthenticationResult"]["AccessToken"] is not None + + @mock_cognitoidp def test_set_user_pool_mfa_config(): conn = boto3.client("cognito-idp", "us-west-2")