Skip to content

Commit 12fab2f

Browse files
authored
fix(auth): Fix for retry sign in when resourceNotFoundException is raised (#2605)
1 parent 3156f9c commit 12fab2f

14 files changed

+575
-31
lines changed

aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/actions/SRPCognitoActions.kt

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package com.amplifyframework.auth.cognito.actions
1818
import aws.sdk.kotlin.services.cognitoidentityprovider.initiateAuth
1919
import aws.sdk.kotlin.services.cognitoidentityprovider.model.AuthFlowType
2020
import aws.sdk.kotlin.services.cognitoidentityprovider.model.ChallengeNameType
21+
import aws.sdk.kotlin.services.cognitoidentityprovider.model.ResourceNotFoundException
2122
import aws.sdk.kotlin.services.cognitoidentityprovider.respondToAuthChallenge
2223
import com.amplifyframework.AmplifyException
2324
import com.amplifyframework.auth.cognito.AuthEnvironment
@@ -27,6 +28,7 @@ import com.amplifyframework.auth.cognito.helpers.SignInChallengeHelper
2728
import com.amplifyframework.auth.exceptions.ServiceException
2829
import com.amplifyframework.statemachine.Action
2930
import com.amplifyframework.statemachine.codegen.actions.SRPActions
31+
import com.amplifyframework.statemachine.codegen.data.CredentialType
3032
import com.amplifyframework.statemachine.codegen.events.AuthenticationEvent
3133
import com.amplifyframework.statemachine.codegen.events.SRPEvent
3234
import com.amplifyframework.statemachine.codegen.events.SignInEvent
@@ -168,17 +170,20 @@ internal object SRPCognitoActions : SRPActions {
168170
dispatcher.send(evt)
169171
}
170172

171-
override fun verifyPasswordSRPAction(event: SRPEvent.EventType.RespondPasswordVerifier) =
173+
override fun verifyPasswordSRPAction(
174+
challengeParameters: Map<String, String>,
175+
metadata: Map<String, String>,
176+
session: String?
177+
) =
172178
Action<AuthEnvironment>("VerifyPasswordSRP") { id, dispatcher ->
173179
logger.verbose("$id Starting execution")
174180
val evt = try {
175-
val params = event.challengeParameters
176-
val salt = params.getValue(KEY_SALT)
177-
val secretBlock = params.getValue(KEY_SECRET_BLOCK)
178-
val srpB = params.getValue(KEY_SRP_B)
179-
val username = params.getValue(KEY_USERNAME)
180-
val userId = params.getValue(KEY_USER_ID_FOR_SRP)
181-
val deviceKey = params.getOrDefault(KEY_DEVICE_KEY, "")
181+
val salt = challengeParameters.getValue(KEY_SALT)
182+
val secretBlock = challengeParameters.getValue(KEY_SECRET_BLOCK)
183+
val srpB = challengeParameters.getValue(KEY_SRP_B)
184+
val username = challengeParameters.getValue(KEY_USERNAME)
185+
val userId = challengeParameters.getValue(KEY_USER_ID_FOR_SRP)
186+
val deviceKey = challengeParameters.getOrDefault(KEY_DEVICE_KEY, "")
182187

183188
srpHelper.setUserPoolParams(userId, configuration.userPool?.poolId!!)
184189

@@ -204,8 +209,8 @@ internal object SRPCognitoActions : SRPActions {
204209
challengeName = ChallengeNameType.PasswordVerifier
205210
clientId = configuration.userPool.appClient
206211
challengeResponses = challengeParams
207-
clientMetadata = event.metadata
208-
session = event.session
212+
clientMetadata = metadata
213+
this.session = session
209214
pinpointEndpointId?.let { analyticsMetadata { analyticsEndpointId = it } }
210215
encodedContextData?.let { userContextData { encodedData = it } }
211216
}
@@ -224,13 +229,28 @@ internal object SRPCognitoActions : SRPActions {
224229
)
225230
}
226231
} catch (e: Exception) {
227-
val errorEvent = SRPEvent(SRPEvent.EventType.ThrowPasswordVerifierError(e))
228-
logger.verbose("$id Sending event ${errorEvent.type}")
229-
dispatcher.send(errorEvent)
230-
val errorEvent2 = SignInEvent(SignInEvent.EventType.ThrowError(e))
231-
logger.verbose("$id Sending event ${errorEvent.type}")
232-
dispatcher.send(errorEvent2)
233-
AuthenticationEvent(AuthenticationEvent.EventType.CancelSignIn())
232+
if (e is ResourceNotFoundException) {
233+
val challengeParams: MutableMap<String, String> = challengeParameters.toMutableMap()
234+
challengeParams.remove(KEY_DEVICE_KEY)
235+
credentialStoreClient.clearCredentials(
236+
CredentialType.Device(
237+
challengeParams.getValue(
238+
KEY_USERNAME
239+
)
240+
)
241+
)
242+
SRPEvent(SRPEvent.EventType.RetryRespondPasswordVerifier(challengeParams, metadata, session))
243+
} else {
244+
val errorEvent = SRPEvent(SRPEvent.EventType.ThrowPasswordVerifierError(e))
245+
logger.verbose("$id Sending event ${errorEvent.type}")
246+
dispatcher.send(errorEvent)
247+
248+
val errorEvent2 = SignInEvent(SignInEvent.EventType.ThrowError(e))
249+
logger.verbose("$id Sending event ${errorEvent.type}")
250+
dispatcher.send(errorEvent2)
251+
252+
AuthenticationEvent(AuthenticationEvent.EventType.CancelSignIn())
253+
}
234254
}
235255
logger.verbose("$id Sending event ${evt.type}")
236256
dispatcher.send(evt)

aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/actions/SignInChallengeCognitoActions.kt

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.amplifyframework.auth.cognito.actions
1717

1818
import aws.sdk.kotlin.services.cognitoidentityprovider.model.ChallengeNameType
19+
import aws.sdk.kotlin.services.cognitoidentityprovider.model.ResourceNotFoundException
1920
import aws.sdk.kotlin.services.cognitoidentityprovider.respondToAuthChallenge
2021
import com.amplifyframework.auth.cognito.AuthEnvironment
2122
import com.amplifyframework.auth.cognito.helpers.AuthHelper
@@ -24,14 +25,16 @@ import com.amplifyframework.auth.exceptions.UnknownException
2425
import com.amplifyframework.statemachine.Action
2526
import com.amplifyframework.statemachine.codegen.actions.SignInChallengeActions
2627
import com.amplifyframework.statemachine.codegen.data.AuthChallenge
28+
import com.amplifyframework.statemachine.codegen.data.CredentialType
2729
import com.amplifyframework.statemachine.codegen.events.CustomSignInEvent
2830
import com.amplifyframework.statemachine.codegen.events.SignInChallengeEvent
2931

3032
internal object SignInChallengeCognitoActions : SignInChallengeActions {
3133
private const val KEY_SECRET_HASH = "SECRET_HASH"
3234
private const val KEY_USERNAME = "USERNAME"
3335
override fun verifyChallengeAuthAction(
34-
event: SignInChallengeEvent.EventType.VerifyChallengeAnswer,
36+
answer: String,
37+
metadata: Map<String, String>,
3538
challenge: AuthChallenge
3639
): Action = Action<AuthEnvironment>("VerifySignInChallenge") { id, dispatcher ->
3740
logger.verbose("$id Starting execution")
@@ -44,7 +47,7 @@ internal object SignInChallengeCognitoActions : SignInChallengeActions {
4447
}
4548

4649
getChallengeResponseKey(challenge.challengeName)?.also { responseKey ->
47-
challengeResponses[responseKey] = event.answer
50+
challengeResponses[responseKey] = answer
4851
}
4952

5053
val secretHash = AuthHelper.getSecretHash(
@@ -61,7 +64,7 @@ internal object SignInChallengeCognitoActions : SignInChallengeActions {
6164
challengeName = ChallengeNameType.fromValue(challenge.challengeName)
6265
this.challengeResponses = challengeResponses
6366
session = challenge.session
64-
clientMetadata = event.metadata
67+
clientMetadata = metadata
6568
pinpointEndpointId?.let { analyticsMetadata { analyticsEndpointId = it } }
6669
encodedContextData?.let { this.userContextData { encodedData = it } }
6770
}
@@ -79,7 +82,20 @@ internal object SignInChallengeCognitoActions : SignInChallengeActions {
7982
)
8083
)
8184
} catch (e: Exception) {
82-
SignInChallengeEvent(SignInChallengeEvent.EventType.ThrowError(e, challenge, true))
85+
if (e is ResourceNotFoundException) {
86+
challenge.username?.let { username ->
87+
credentialStoreClient.clearCredentials(CredentialType.Device(username))
88+
}
89+
SignInChallengeEvent(
90+
SignInChallengeEvent.EventType.RetryVerifyChallengeAnswer(
91+
answer,
92+
metadata,
93+
challenge
94+
)
95+
)
96+
} else {
97+
SignInChallengeEvent(SignInChallengeEvent.EventType.ThrowError(e, challenge, true))
98+
}
8399
}
84100
logger.verbose("$id Sending event ${evt.type}")
85101
dispatcher.send(evt)

aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/actions/SRPActions.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,9 @@ import com.amplifyframework.statemachine.codegen.events.SRPEvent
2121
internal interface SRPActions {
2222
fun initiateSRPAuthAction(event: SRPEvent.EventType.InitiateSRP): Action
2323
fun initiateSRPWithCustomAuthAction(event: SRPEvent.EventType.InitiateSRPWithCustom): Action
24-
fun verifyPasswordSRPAction(event: SRPEvent.EventType.RespondPasswordVerifier): Action
24+
fun verifyPasswordSRPAction(
25+
challengeParameters: Map<String, String>,
26+
metadata: Map<String, String>,
27+
session: String?
28+
): Action
2529
}

aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/actions/SignInChallengeActions.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ package com.amplifyframework.statemachine.codegen.actions
1717

1818
import com.amplifyframework.statemachine.Action
1919
import com.amplifyframework.statemachine.codegen.data.AuthChallenge
20-
import com.amplifyframework.statemachine.codegen.events.SignInChallengeEvent
2120

2221
internal interface SignInChallengeActions {
2322
fun verifyChallengeAuthAction(
24-
event: SignInChallengeEvent.EventType.VerifyChallengeAnswer,
23+
answer: String,
24+
metadata: Map<String, String>,
2525
challenge: AuthChallenge
2626
): Action
2727
}

aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/events/SRPEvent.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ internal class SRPEvent(val eventType: EventType, override val time: Date? = nul
3737
val session: String?
3838
) : EventType()
3939

40+
data class RetryRespondPasswordVerifier(
41+
val challengeParameters: Map<String, String>,
42+
val metadata: Map<String, String>,
43+
val session: String?
44+
) : EventType()
45+
4046
data class ThrowAuthError(val exception: Exception) : EventType()
4147
data class CancelSRPSignIn(val id: String = "") : EventType()
4248
data class ThrowPasswordVerifierError(val exception: Exception) : EventType()

aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/events/SignInChallengeEvent.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ internal class SignInChallengeEvent(val eventType: EventType, override val time:
2323
sealed class EventType {
2424
data class WaitForAnswer(val challenge: AuthChallenge, val hasNewResponse: Boolean = false) : EventType()
2525
data class VerifyChallengeAnswer(val answer: String, val metadata: Map<String, String>) : EventType()
26+
27+
data class RetryVerifyChallengeAnswer(
28+
val answer: String,
29+
val metadata: Map<String, String>,
30+
val authChallenge: AuthChallenge
31+
) : EventType()
2632
data class FinalizeSignIn(val accessToken: String) : EventType()
2733
data class Verified(val id: String = "") : EventType()
2834
data class ThrowError(

aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/states/SRPSignInState.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,22 @@ internal sealed class SRPSignInState : State {
5454
}
5555
is InitiatingSRPA -> when (srpEvent) {
5656
is SRPEvent.EventType.RespondPasswordVerifier -> {
57-
val action = srpActions.verifyPasswordSRPAction(srpEvent)
57+
val action = srpActions.verifyPasswordSRPAction(
58+
srpEvent.challengeParameters, srpEvent.metadata, srpEvent.session
59+
)
5860
StateResolution(RespondingPasswordVerifier(), listOf(action))
5961
}
6062
is SRPEvent.EventType.ThrowAuthError -> StateResolution(Error(srpEvent.exception))
6163
is SRPEvent.EventType.CancelSRPSignIn -> StateResolution(Cancelling())
6264
else -> defaultResolution
6365
}
6466
is RespondingPasswordVerifier -> when (srpEvent) {
67+
is SRPEvent.EventType.RetryRespondPasswordVerifier -> {
68+
val action = srpActions.verifyPasswordSRPAction(
69+
srpEvent.challengeParameters, srpEvent.metadata, srpEvent.session
70+
)
71+
StateResolution(RespondingPasswordVerifier(), listOf(action))
72+
}
6573
is SRPEvent.EventType.ThrowPasswordVerifierError -> StateResolution(Error(srpEvent.exception))
6674
is SRPEvent.EventType.CancelSRPSignIn -> StateResolution(Cancelling())
6775
else -> defaultResolution

aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/states/SignInChallengeState.kt

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,28 @@ internal sealed class SignInChallengeState : State {
5959
}
6060
is WaitingForAnswer -> when (challengeEvent) {
6161
is SignInChallengeEvent.EventType.VerifyChallengeAnswer -> {
62-
val action = challengeActions.verifyChallengeAuthAction(challengeEvent, oldState.challenge)
62+
val action = challengeActions.verifyChallengeAuthAction(
63+
challengeEvent.answer, challengeEvent.metadata, oldState.challenge
64+
)
6365
StateResolution(Verifying(oldState.challenge.challengeName), listOf(action))
6466
}
6567
else -> defaultResolution
6668
}
6769
is Verifying -> when (challengeEvent) {
6870
is SignInChallengeEvent.EventType.Verified -> StateResolution(Verified())
6971
is SignInChallengeEvent.EventType.ThrowError -> {
70-
StateResolution(Error(challengeEvent.exception, challengeEvent.challenge, true), listOf())
72+
StateResolution(
73+
Error(
74+
challengeEvent.exception, challengeEvent.challenge, true
75+
),
76+
listOf()
77+
)
78+
}
79+
is SignInChallengeEvent.EventType.RetryVerifyChallengeAnswer -> {
80+
val action = challengeActions.verifyChallengeAuthAction(
81+
challengeEvent.answer, challengeEvent.metadata, challengeEvent.authChallenge
82+
)
83+
StateResolution(Verifying(challengeEvent.authChallenge.challengeName), listOf(action))
7184
}
7285
is SignInChallengeEvent.EventType.WaitForAnswer -> {
7386
StateResolution(WaitingForAnswer(challengeEvent.challenge, true), listOf())
@@ -78,7 +91,9 @@ internal sealed class SignInChallengeState : State {
7891
is Error -> {
7992
when (challengeEvent) {
8093
is SignInChallengeEvent.EventType.VerifyChallengeAnswer -> {
81-
val action = challengeActions.verifyChallengeAuthAction(challengeEvent, oldState.challenge)
94+
val action = challengeActions.verifyChallengeAuthAction(
95+
challengeEvent.answer, challengeEvent.metadata, oldState.challenge
96+
)
8297
StateResolution(Verifying(oldState.challenge.challengeName), listOf(action))
8398
}
8499
is SignInChallengeEvent.EventType.WaitForAnswer -> {

aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/StateTransitionTestBase.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,15 @@ open class StateTransitionTestBase {
265265
Mockito.`when`(mockSignInActions.startSRPAuthAction(MockitoHelper.anyObject()))
266266
.thenReturn(
267267
Action { dispatcher, _ ->
268-
dispatcher.send(SRPEvent(SRPEvent.EventType.InitiateSRP("username", "password", mapOf())))
268+
dispatcher.send(
269+
SRPEvent(
270+
SRPEvent.EventType.InitiateSRP(
271+
"username",
272+
"password",
273+
mapOf()
274+
)
275+
)
276+
)
269277
}
270278
)
271279

@@ -319,6 +327,7 @@ open class StateTransitionTestBase {
319327

320328
Mockito.`when`(
321329
mockSignInChallengeActions.verifyChallengeAuthAction(
330+
MockitoHelper.anyObject(),
322331
MockitoHelper.anyObject(),
323332
MockitoHelper.anyObject()
324333
)
@@ -355,7 +364,13 @@ open class StateTransitionTestBase {
355364
}
356365
)
357366

358-
Mockito.`when`(mockSRPActions.verifyPasswordSRPAction(MockitoHelper.anyObject()))
367+
Mockito.`when`(
368+
mockSRPActions.verifyPasswordSRPAction(
369+
MockitoHelper.anyObject(),
370+
MockitoHelper.anyObject(),
371+
MockitoHelper.anyObject()
372+
)
373+
)
359374
.thenReturn(
360375
Action { dispatcher, _ ->
361376
dispatcher.send(

0 commit comments

Comments
 (0)