Skip to content

Commit

Permalink
feat(Auth): Overriding sign in when the State machine is already in t…
Browse files Browse the repository at this point in the history
…he signing in state (#2187)
  • Loading branch information
gpanshu committed Dec 21, 2022
1 parent f562b1e commit b075845
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 11 deletions.
Expand Up @@ -464,19 +464,37 @@ internal class RealAWSCognitoAuthPlugin(
onError: Consumer<AuthException>
) {
authStateMachine.getCurrentState { authState ->
val signInOptions = options as? AWSCognitoAuthSignInOptions ?: AWSCognitoAuthSignInOptions.builder()
.authFlowType(configuration.authFlowType)
.build()
when (authState.authNState) {
is AuthenticationState.NotConfigured -> onError.accept(
InvalidUserPoolConfigurationException()
)
// Continue sign in
is AuthenticationState.SignedOut, is AuthenticationState.Configured -> {
val signInOptions = options as? AWSCognitoAuthSignInOptions ?: AWSCognitoAuthSignInOptions.builder()
.authFlowType(configuration.authFlowType)
.build()

is AuthenticationState.SignedOut,
is AuthenticationState.Configured -> {
_signIn(username, password, signInOptions, onSuccess, onError)
}
is AuthenticationState.SignedIn -> onError.accept(SignedInException())
is AuthenticationState.SigningIn -> {
val token = StateChangeListenerToken()
authStateMachine.listen(
token,
{ authState ->
when (authState.authNState) {
is AuthenticationState.SignedOut -> {
authStateMachine.cancel(token)
_signIn(username, password, signInOptions, onSuccess, onError)
}
else -> Unit
}
},
{
authStateMachine.send(AuthenticationEvent(AuthenticationEvent.EventType.CancelSignIn()))
}
)
}
else -> onError.accept(InvalidStateException())
}
}
Expand Down Expand Up @@ -706,6 +724,30 @@ internal class RealAWSCognitoAuthPlugin(
)
}
is AuthenticationState.SignedIn -> onError.accept(SignedInException())
is AuthenticationState.SigningIn -> {
val token = StateChangeListenerToken()
authStateMachine.listen(
token,
{ authState ->
when (authState.authNState) {
is AuthenticationState.SignedOut -> {
authStateMachine.cancel(token)
_signInWithHostedUI(
callingActivity = callingActivity,
options = options,
onSuccess = onSuccess,
onError = onError,
provider = provider
)
}
else -> Unit
}
},
{
authStateMachine.send(AuthenticationEvent(AuthenticationEvent.EventType.CancelSignIn()))
}
)
}
else -> onError.accept(InvalidStateException())
}
}
Expand Down
Expand Up @@ -18,7 +18,6 @@ package com.amplifyframework.auth.cognito
import aws.sdk.kotlin.services.cognitoidentityprovider.CognitoIdentityProviderClient
import aws.sdk.kotlin.services.cognitoidentityprovider.model.AnalyticsMetadataType
import aws.sdk.kotlin.services.cognitoidentityprovider.model.AttributeType
import aws.sdk.kotlin.services.cognitoidentityprovider.model.ChangePasswordRequest
import aws.sdk.kotlin.services.cognitoidentityprovider.model.ChangePasswordResponse
import aws.sdk.kotlin.services.cognitoidentityprovider.model.CodeDeliveryDetailsType
import aws.sdk.kotlin.services.cognitoidentityprovider.model.CognitoIdentityProviderException
Expand All @@ -44,7 +43,6 @@ import com.amplifyframework.auth.AuthException
import com.amplifyframework.auth.AuthUserAttribute
import com.amplifyframework.auth.AuthUserAttributeKey
import com.amplifyframework.auth.cognito.exceptions.configuration.InvalidUserPoolConfigurationException
import com.amplifyframework.auth.cognito.exceptions.invalidstate.SignedInException
import com.amplifyframework.auth.cognito.helpers.AuthHelper
import com.amplifyframework.auth.cognito.helpers.SRPHelper
import com.amplifyframework.auth.cognito.options.AWSCognitoAuthResendUserAttributeConfirmationCodeOptions
Expand Down Expand Up @@ -223,6 +221,7 @@ class RealAWSCognitoAuthPluginTest {
val expectedAuthError = InvalidUserPoolConfigurationException()
currentState = AuthenticationState.NotConfigured()

coEvery { authConfiguration.authFlowType } returns AuthFlowType.USER_SRP_AUTH
// WHEN
plugin.signIn("user", "password", AuthSignInOptions.defaults(), onSuccess, onError)

Expand All @@ -236,7 +235,7 @@ class RealAWSCognitoAuthPluginTest {
// GIVEN
val onSuccess = mockk<Consumer<AuthSignInResult>>()
val onError = mockk<Consumer<AuthException>>(relaxed = true)
val expectedAuthError = SignedInException()
coEvery { authConfiguration.authFlowType } returns AuthFlowType.USER_SRP_AUTH
currentState = AuthenticationState.SignedIn(
SignedInData(
"userId",
Expand All @@ -253,7 +252,7 @@ class RealAWSCognitoAuthPluginTest {

// THEN
verify(exactly = 0) { onSuccess.accept(any()) }
verify { onError.accept(expectedAuthError) }
verify { onError.accept(any()) }
}

@Test
Expand Down Expand Up @@ -290,7 +289,7 @@ class RealAWSCognitoAuthPluginTest {
}

coEvery {
authService.cognitoIdentityProviderClient?.changePassword(any<ChangePasswordRequest>())
authService.cognitoIdentityProviderClient?.changePassword(any())
} returns ChangePasswordResponse.invoke { }

// WHEN
Expand Down
Expand Up @@ -271,6 +271,30 @@ object SignInTestCaseGenerator : SerializableProvider {
)
)

private val signInWhenAlreadySigningInAuthCase = FeatureTestCase(
description = "Test that overriding signIn when already signing in returns success",
preConditions = PreConditions(
"authconfiguration.json",
"SigningIn_SigningIn.json",
mockedResponses = listOf(
mockedInitiateAuthResponse,
mockedSMSChallengeResponse,
)
),
api = API(
AuthAPI.signIn,
params = mapOf(
"username" to username,
"password" to password
).toJsonElement(),
options = JsonObject(emptyMap())
),
validations = listOf(
mockedSignInSMSChallengeExpectation,
ExpectationShapes.State("SigningIn_SigningIn.json")
)
)

private val customAuthCase = FeatureTestCase(
description = "Test that Custom Auth signIn invokes proper cognito request and returns custom challenge",
preConditions = PreConditions(
Expand Down Expand Up @@ -325,6 +349,11 @@ object SignInTestCaseGenerator : SerializableProvider {
)

override val serializables: List<Any> = listOf(
baseCase, challengeCase, deviceSRPTestCase, customAuthCase, customAuthWithSRPCase
baseCase,
challengeCase,
deviceSRPTestCase,
customAuthCase,
customAuthWithSRPCase,
signInWhenAlreadySigningInAuthCase
)
}
@@ -0,0 +1,69 @@
{
"description": "Test that overriding signIn when already signing in returns success",
"preConditions": {
"amplify-configuration": "authconfiguration.json",
"state": "SigningIn_SigningIn.json",
"mockedResponses": [
{
"type": "cognitoIdentityProvider",
"apiName": "initiateAuth",
"responseType": "success",
"response": {
"challengeName": "PASSWORD_VERIFIER",
"challengeParameters": {
"SALT": "abc",
"SECRET_BLOCK": "secretBlock",
"SRP_B": "def",
"USERNAME": "username",
"USER_ID_FOR_SRP": "userId"
}
}
},
{
"type": "cognitoIdentityProvider",
"apiName": "respondToAuthChallenge",
"responseType": "success",
"response": {
"session": "someSession",
"challengeName": "SMS_MFA",
"challengeParameters": {
"CODE_DELIVERY_DELIVERY_MEDIUM": "SMS",
"CODE_DELIVERY_DESTINATION": "+12345678900"
}
}
}
]
},
"api": {
"name": "signIn",
"params": {
"username": "username",
"password": "password"
},
"options": {
}
},
"validations": [
{
"type": "amplify",
"apiName": "signIn",
"responseType": "success",
"response": {
"isSignedIn": false,
"nextStep": {
"signInStep": "CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE",
"additionalInfo": {
},
"codeDeliveryDetails": {
"destination": "+12345678900",
"deliveryMedium": "SMS"
}
}
}
},
{
"type": "state",
"expectedState": "SigningIn_SigningIn.json"
}
]
}

0 comments on commit b075845

Please sign in to comment.