@@ -3134,7 +3134,6 @@ def test_authentication_flow_invalid_flow():
31343134 == "1 validation error detected: Value 'NO_SUCH_FLOW' at 'authFlow' failed to satisfy constraint: Member must satisfy enum value set: ['ADMIN_NO_SRP_AUTH', 'ADMIN_USER_PASSWORD_AUTH', 'USER_SRP_AUTH', 'REFRESH_TOKEN_AUTH', 'REFRESH_TOKEN', 'CUSTOM_AUTH', 'USER_PASSWORD_AUTH']"
31353135 )
31363136
3137-
31383137@mock_aws
31393138def test_authentication_flow_invalid_user_flow ():
31403139 """Pass a user authFlow to admin_initiate_auth"""
@@ -3294,6 +3293,7 @@ def user_authentication_flow(
32943293
32953294
32963295@cognitoidp_aws_verified (generate_secret = True , with_mfa = "ON" )
3296+ @mock .patch .dict (os .environ , {"MOTO_COGNITO_IDP_USER_POOL_ENABLE_TOTP" : "true" })
32973297@pytest .mark .aws_verified
32983298def test_user_authentication_flow_mfa_on (user_pool = None , user_pool_client = None ):
32993299 conn = boto3 .client ("cognito-idp" , "us-west-2" )
@@ -3397,6 +3397,7 @@ def test_user_authentication_flow_mfa_on(user_pool=None, user_pool_client=None):
33973397
33983398
33993399@cognitoidp_aws_verified (generate_secret = True , with_mfa = "OPTIONAL" )
3400+ @mock .patch .dict (os .environ , {"MOTO_COGNITO_IDP_USER_POOL_ENABLE_TOTP" : "true" })
34003401@pytest .mark .aws_verified
34013402def test_user_authentication_flow_mfa_optional (user_pool = None , user_pool_client = None ):
34023403 conn = boto3 .client ("cognito-idp" , "us-west-2" )
@@ -5019,6 +5020,7 @@ def test_initiate_auth_USER_PASSWORD_AUTH_with_FORCE_CHANGE_PASSWORD_status():
50195020
50205021
50215022@cognitoidp_aws_verified (explicit_auth_flows = ["USER_PASSWORD_AUTH" ], with_mfa = "ON" )
5023+ @mock .patch .dict (os .environ , {"MOTO_COGNITO_IDP_USER_POOL_ENABLE_TOTP" : "true" })
50225024@pytest .mark .aws_verified
50235025def test_initiate_mfa_auth_USER_PASSWORD_AUTH_with_FORCE_CHANGE_PASSWORD_status (
50245026 user_pool = None , user_pool_client = None
@@ -5241,6 +5243,7 @@ def test_initiate_auth_with_invalid_secret_hash():
52415243
52425244
52435245@mock_aws
5246+ @mock .patch .dict (os .environ , {"MOTO_COGNITO_IDP_USER_POOL_ENABLE_TOTP" : "true" })
52445247def test_setting_mfa ():
52455248 conn = boto3 .client ("cognito-idp" , "us-west-2" )
52465249
@@ -5329,6 +5332,7 @@ def test_admin_setting_single_mfa():
53295332
53305333
53315334@mock_aws
5335+ @mock .patch .dict (os .environ , {"MOTO_COGNITO_IDP_USER_POOL_ENABLE_TOTP" : "true" })
53325336def test_admin_setting_mfa_totp_and_sms ():
53335337 conn = boto3 .client ("cognito-idp" , "us-west-2" )
53345338
@@ -5365,8 +5369,67 @@ def test_admin_setting_mfa_totp_and_sms():
53655369 assert len (result ["UserMFASettingList" ]) == 0
53665370 assert result ["PreferredMfaSetting" ] == ""
53675371
5372+ @mock_aws
5373+ def test_admin_initiate_auth_when_token_totp_masked ():
5374+ conn = boto3 .client ("cognito-idp" , "us-west-2" )
5375+
5376+ result = authentication_flow (conn , "ADMIN_NO_SRP_AUTH" )
5377+ access_token = result ["access_token" ]
5378+ user_pool_id = result ["user_pool_id" ]
5379+ username = result ["username" ]
5380+ client_id = result ["client_id" ]
5381+ password = result ["password" ]
5382+ resp = conn .associate_software_token (AccessToken = access_token )
5383+ secret_code = resp ["SecretCode" ]
5384+ totp = pyotp .TOTP (secret_code )
5385+ user_code = totp .now ()
5386+ conn .verify_software_token (AccessToken = access_token , UserCode = user_code )
5387+
5388+ # Set MFA TOTP and SMS methods
5389+ conn .admin_set_user_mfa_preference (
5390+ Username = username ,
5391+ UserPoolId = user_pool_id ,
5392+ SoftwareTokenMfaSettings = {"Enabled" : True , "PreferredMfa" : True },
5393+ SMSMfaSettings = {"Enabled" : True , "PreferredMfa" : False },
5394+ )
5395+ result = conn .admin_get_user (UserPoolId = user_pool_id , Username = username )
5396+ assert len (result ["UserMFASettingList" ]) == 2
5397+ assert result ["PreferredMfaSetting" ] == "SOFTWARE_TOKEN_MFA"
5398+
5399+ # Initiate auth with TOTP
5400+ result = conn .admin_initiate_auth (
5401+ UserPoolId = user_pool_id ,
5402+ ClientId = client_id ,
5403+ AuthFlow = "ADMIN_NO_SRP_AUTH" ,
5404+ AuthParameters = {
5405+ "USERNAME" : username ,
5406+ "PASSWORD" : password ,
5407+ },
5408+ )
5409+
5410+ assert result ["ChallengeName" ] == "SOFTWARE_TOKEN_MFA"
5411+ assert result ["Session" ] != ""
5412+
5413+ # Respond to challenge with TOTP
5414+ result = conn .admin_respond_to_auth_challenge (
5415+ UserPoolId = user_pool_id ,
5416+ ClientId = client_id ,
5417+ ChallengeName = "SOFTWARE_TOKEN_MFA" ,
5418+ Session = result ["Session" ],
5419+ ChallengeResponses = {
5420+ "SOFTWARE_TOKEN_MFA_CODE" : "123456" ,
5421+ "USERNAME" : username ,
5422+ },
5423+ )
5424+
5425+ assert result ["AuthenticationResult" ]["IdToken" ] != ""
5426+ assert result ["AuthenticationResult" ]["AccessToken" ] != ""
5427+ assert result ["AuthenticationResult" ]["RefreshToken" ] != ""
5428+ assert result ["AuthenticationResult" ]["TokenType" ] == "Bearer"
5429+
53685430
53695431@mock_aws
5432+ @mock .patch .dict (os .environ , {"MOTO_COGNITO_IDP_USER_POOL_ENABLE_TOTP" : "true" })
53705433def test_admin_initiate_auth_when_token_totp_enabled ():
53715434 conn = boto3 .client ("cognito-idp" , "us-west-2" )
53725435
@@ -5414,7 +5477,7 @@ def test_admin_initiate_auth_when_token_totp_enabled():
54145477 ChallengeName = "SOFTWARE_TOKEN_MFA" ,
54155478 Session = result ["Session" ],
54165479 ChallengeResponses = {
5417- "SOFTWARE_TOKEN_MFA_CODE" : "123456" ,
5480+ "SOFTWARE_TOKEN_MFA_CODE" : totp . now () ,
54185481 "USERNAME" : username ,
54195482 },
54205483 )
@@ -5425,6 +5488,63 @@ def test_admin_initiate_auth_when_token_totp_enabled():
54255488 assert result ["AuthenticationResult" ]["TokenType" ] == "Bearer"
54265489
54275490
5491+ @mock_aws
5492+ @mock .patch .dict (os .environ , {"MOTO_COGNITO_IDP_USER_POOL_ENABLE_TOTP" : "true" })
5493+ def test_admin_initiate_auth_when_token_totp_enabled_invalid ():
5494+ conn = boto3 .client ("cognito-idp" , "us-west-2" )
5495+
5496+ result = authentication_flow (conn , "ADMIN_NO_SRP_AUTH" )
5497+ access_token = result ["access_token" ]
5498+ user_pool_id = result ["user_pool_id" ]
5499+ username = result ["username" ]
5500+ client_id = result ["client_id" ]
5501+ password = result ["password" ]
5502+ resp = conn .associate_software_token (AccessToken = access_token )
5503+ secret_code = resp ["SecretCode" ]
5504+ totp = pyotp .TOTP (secret_code )
5505+ user_code = totp .now ()
5506+ conn .verify_software_token (AccessToken = access_token , UserCode = user_code )
5507+
5508+ # Set MFA TOTP and SMS methods
5509+ conn .admin_set_user_mfa_preference (
5510+ Username = username ,
5511+ UserPoolId = user_pool_id ,
5512+ SoftwareTokenMfaSettings = {"Enabled" : True , "PreferredMfa" : True },
5513+ SMSMfaSettings = {"Enabled" : True , "PreferredMfa" : False },
5514+ )
5515+ result = conn .admin_get_user (UserPoolId = user_pool_id , Username = username )
5516+ assert len (result ["UserMFASettingList" ]) == 2
5517+ assert result ["PreferredMfaSetting" ] == "SOFTWARE_TOKEN_MFA"
5518+
5519+ # Initiate auth with TOTP
5520+ result = conn .admin_initiate_auth (
5521+ UserPoolId = user_pool_id ,
5522+ ClientId = client_id ,
5523+ AuthFlow = "ADMIN_NO_SRP_AUTH" ,
5524+ AuthParameters = {
5525+ "USERNAME" : username ,
5526+ "PASSWORD" : password ,
5527+ },
5528+ )
5529+
5530+ assert result ["ChallengeName" ] == "SOFTWARE_TOKEN_MFA"
5531+ assert result ["Session" ] != ""
5532+
5533+ with pytest .raises (ClientError ) as exc :
5534+ result = conn .admin_respond_to_auth_challenge (
5535+ UserPoolId = user_pool_id ,
5536+ ClientId = client_id ,
5537+ ChallengeName = "SOFTWARE_TOKEN_MFA" ,
5538+ Session = result ["Session" ],
5539+ ChallengeResponses = {
5540+ "SOFTWARE_TOKEN_MFA_CODE" : "123456" ,
5541+ "USERNAME" : username ,
5542+ },
5543+ )
5544+ err = exc .value .response ["Error" ]
5545+ assert err ["Code" ] == "CodeMismatch"
5546+
5547+
54285548@mock_aws
54295549def test_admin_initiate_auth_when_sms_mfa_enabled ():
54305550 conn = boto3 .client ("cognito-idp" , "us-west-2" )
0 commit comments