From d0286719f840c7ada96528e18767ddafe58f90ed Mon Sep 17 00:00:00 2001 From: Matt Creaser Date: Tue, 16 Jan 2024 13:45:25 -0400 Subject: [PATCH] fix(auth): Add MFAType.challengeResponse extension (#2680) --- .../auth/cognito/MFATypeUtil.kt | 30 +++++++++++++++++ .../auth/cognito/RealAWSCognitoAuthPlugin.kt | 27 ++++++++++++---- .../auth/cognito/helpers/MFAHelper.kt | 17 ++++++---- .../auth/cognito/MFATypeUtilTest.kt | 32 +++++++++++++++++++ 4 files changed, 92 insertions(+), 14 deletions(-) create mode 100644 aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/MFATypeUtil.kt create mode 100644 aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/MFATypeUtilTest.kt diff --git a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/MFATypeUtil.kt b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/MFATypeUtil.kt new file mode 100644 index 0000000000..ca4bc57435 --- /dev/null +++ b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/MFATypeUtil.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +@file:JvmName("MFATypeUtil") + +package com.amplifyframework.auth.cognito + +import com.amplifyframework.auth.MFAType + +/** + * Returns the cognito-specific string to pass to Amplify.Auth.confirmSignIn for a specific [MFAType] when making + * an MFA selection during the sign-in process. + */ +val MFAType.challengeResponse: String + get() = when (this) { + MFAType.SMS -> "SMS_MFA" + MFAType.TOTP -> "SOFTWARE_TOKEN_MFA" + } diff --git a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPlugin.kt b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPlugin.kt index 5f938178ae..84a307b8b6 100644 --- a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPlugin.kt +++ b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPlugin.kt @@ -71,7 +71,9 @@ import com.amplifyframework.auth.cognito.helpers.HostedUIHelper import com.amplifyframework.auth.cognito.helpers.SessionHelper import com.amplifyframework.auth.cognito.helpers.SignInChallengeHelper import com.amplifyframework.auth.cognito.helpers.getMFAType +import com.amplifyframework.auth.cognito.helpers.getMFATypeOrNull import com.amplifyframework.auth.cognito.helpers.identityProviderName +import com.amplifyframework.auth.cognito.helpers.value import com.amplifyframework.auth.cognito.options.AWSCognitoAuthConfirmResetPasswordOptions import com.amplifyframework.auth.cognito.options.AWSCognitoAuthConfirmSignInOptions import com.amplifyframework.auth.cognito.options.AWSCognitoAuthConfirmSignUpOptions @@ -789,14 +791,25 @@ internal class RealAWSCognitoAuthPlugin( val userAttributes = awsCognitoConfirmSignInOptions?.userAttributes ?: emptyList() when (signInState) { is SignInState.ResolvingChallenge -> { - val event = SignInChallengeEvent( - SignInChallengeEvent.EventType.VerifyChallengeAnswer( - challengeResponse, - metadata, - userAttributes + val challengeState = signInState.challengeState + if (challengeState is SignInChallengeState.WaitingForAnswer && + challengeState.challenge.challengeName == "SELECT_MFA_TYPE" && + getMFATypeOrNull(challengeResponse) == null + ) { + val error = InvalidParameterException( + message = "Value for challengeResponse must be one of SMS_MFA or SOFTWARE_TOKEN_MFA" ) - ) - authStateMachine.send(event) + onError.accept(error) + } else { + val event = SignInChallengeEvent( + SignInChallengeEvent.EventType.VerifyChallengeAnswer( + challengeResponse, + metadata, + userAttributes + ) + ) + authStateMachine.send(event) + } } is SignInState.ResolvingTOTPSetup -> { diff --git a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/helpers/MFAHelper.kt b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/helpers/MFAHelper.kt index 219b43e370..c3bf3b8a60 100644 --- a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/helpers/MFAHelper.kt +++ b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/helpers/MFAHelper.kt @@ -16,15 +16,18 @@ package com.amplifyframework.auth.cognito.helpers import com.amplifyframework.auth.MFAType -import kotlin.jvm.Throws @Throws(IllegalArgumentException::class) -internal fun getMFAType(value: String): MFAType { - return when (value) { - "SMS_MFA" -> MFAType.SMS - "SOFTWARE_TOKEN_MFA" -> MFAType.TOTP - else -> throw IllegalArgumentException("Unsupported MFA type") - } +internal fun getMFAType(value: String) = when (value) { + "SMS_MFA" -> MFAType.SMS + "SOFTWARE_TOKEN_MFA" -> MFAType.TOTP + else -> throw IllegalArgumentException("Unsupported MFA type") +} + +internal fun getMFATypeOrNull(value: String) = when (value) { + "SMS_MFA" -> MFAType.SMS + "SOFTWARE_TOKEN_MFA" -> MFAType.TOTP + else -> null } internal val MFAType.value: String diff --git a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/MFATypeUtilTest.kt b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/MFATypeUtilTest.kt new file mode 100644 index 0000000000..5a754efdf2 --- /dev/null +++ b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/MFATypeUtilTest.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.amplifyframework.auth.cognito + +import com.amplifyframework.auth.MFAType +import kotlin.test.assertEquals +import org.junit.Test + +class MFATypeUtilTest { + @Test + fun challengeResponse_returns_correct_sms_string() { + assertEquals("SMS_MFA", MFAType.SMS.challengeResponse) + } + + @Test + fun challengeResponse_returns_correct_totp_string() { + assertEquals("SOFTWARE_TOKEN_MFA", MFAType.TOTP.challengeResponse) + } +}