diff --git a/moto/cognitoidp/models.py b/moto/cognitoidp/models.py index f189f593e..d7911ec42 100644 --- a/moto/cognitoidp/models.py +++ b/moto/cognitoidp/models.py @@ -1486,6 +1486,13 @@ class CognitoIdpBackend(BaseBackend): session = str(uuid.uuid4()) self.sessions[session] = user_pool + if user.status is UserStatus.FORCE_CHANGE_PASSWORD: + return { + "ChallengeName": "NEW_PASSWORD_REQUIRED", + "ChallengeParameters": {"USERNAME": user.username}, + "Session": session, + } + access_token, expires_in = user_pool.create_access_token( client_id, username ) diff --git a/tests/test_cognitoidp/test_cognitoidp.py b/tests/test_cognitoidp/test_cognitoidp.py index b44a6ad4a..c6d518f85 100644 --- a/tests/test_cognitoidp/test_cognitoidp.py +++ b/tests/test_cognitoidp/test_cognitoidp.py @@ -3357,6 +3357,57 @@ def test_initiate_auth_USER_PASSWORD_AUTH(): result["AuthenticationResult"]["RefreshToken"].should_not.be.none +@mock_cognitoidp +def test_initiate_auth_USER_PASSWORD_AUTH_with_FORCE_CHANGE_PASSWORD_status(): + # Test flow: + # 1. Create user with FORCE_CHANGE_PASSWORD status + # 2. Login with temporary password + # 3. Check that the right challenge is received + # 4. Respond to challenge with new password + # 5. Check that the access tokens are received + + client = boto3.client("cognito-idp", "us-west-2") + username = str(uuid.uuid4()) + + # Create pool and client + user_pool_id = client.create_user_pool(PoolName=str(uuid.uuid4()))["UserPool"]["Id"] + + client_id = client.create_user_pool_client( + UserPoolId=user_pool_id, ClientName=str(uuid.uuid4()), GenerateSecret=True, + )["UserPoolClient"]["ClientId"] + + # Create user in status FORCE_CHANGE_PASSWORD + temporary_password = str(uuid.uuid4()) + client.admin_create_user( + UserPoolId=user_pool_id, Username=username, TemporaryPassword=temporary_password + ) + + result = client.initiate_auth( + ClientId=client_id, + AuthFlow="USER_PASSWORD_AUTH", + AuthParameters={"USERNAME": username, "PASSWORD": temporary_password}, + ) + + result["ChallengeName"].should.equal("NEW_PASSWORD_REQUIRED") + result["ChallengeParameters"]["USERNAME"].should.equal(username) + result["Session"].should_not.be.none + assert result.get("AuthenticationResult") is None + + new_password = str(uuid.uuid4()) + result = client.respond_to_auth_challenge( + ClientId=client_id, + ChallengeName="NEW_PASSWORD_REQUIRED", + Session=result["Session"], + ChallengeResponses={ + "NEW_PASSWORD": new_password, + "USERNAME": result["ChallengeParameters"]["USERNAME"], + }, + ) + + result["AuthenticationResult"]["IdToken"].should_not.be.none + result["AuthenticationResult"]["AccessToken"].should_not.be.none + + @mock_cognitoidp def test_initiate_auth_USER_PASSWORD_AUTH_user_not_found(): conn = boto3.client("cognito-idp", "us-west-2")