Skip to content

Commit ef37f18

Browse files
authored
fix(auth): Add missing state transitions for AutoSignIn state (#3138)
1 parent 71771e4 commit ef37f18

File tree

15 files changed

+515
-749
lines changed

15 files changed

+515
-749
lines changed

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

Lines changed: 35 additions & 219 deletions
Large diffs are not rendered by default.

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ internal object SignInChallengeCognitoActions : SignInChallengeActions {
4141
override fun verifyChallengeAuthAction(
4242
answer: String,
4343
metadata: Map<String, String>,
44-
attributes: List<AuthUserAttribute>,
44+
userAttributes: List<AuthUserAttribute>,
4545
challenge: AuthChallenge,
4646
signInMethod: SignInMethod
4747
): Action = Action<AuthEnvironment>("VerifySignInChallenge") { id, dispatcher ->
@@ -76,7 +76,7 @@ internal object SignInChallengeCognitoActions : SignInChallengeActions {
7676
}
7777

7878
challengeResponses.putAll(
79-
attributes.map {
79+
userAttributes.map {
8080
Pair("${KEY_PREFIX_USER_ATTRIBUTE}${it.key.keyString}", it.value)
8181
}
8282
)
@@ -122,12 +122,12 @@ internal object SignInChallengeCognitoActions : SignInChallengeActions {
122122
SignInChallengeEvent.EventType.RetryVerifyChallengeAnswer(
123123
answer,
124124
metadata,
125-
attributes,
125+
userAttributes,
126126
challenge
127127
)
128128
)
129129
} else {
130-
SignInChallengeEvent(SignInChallengeEvent.EventType.ThrowError(e, challenge, true))
130+
SignInChallengeEvent(SignInChallengeEvent.EventType.ThrowError(e, challenge))
131131
}
132132
}
133133
logger.verbose("$id Sending event ${evt.type}")

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ internal object SignInCognitoActions : SignInActions {
109109
Action<AuthEnvironment>("InitResolveChallenge") { id, dispatcher ->
110110
logger.verbose("$id Starting execution")
111111
val evt = SignInChallengeEvent(
112-
SignInChallengeEvent.EventType.WaitForAnswer(event.challenge, event.signInMethod, true)
112+
SignInChallengeEvent.EventType.WaitForAnswer(event.challenge, event.signInMethod)
113113
)
114114
logger.verbose("$id Sending event ${evt.type}")
115115
dispatcher.send(evt)
@@ -229,6 +229,7 @@ internal object SignInCognitoActions : SignInActions {
229229
session = response.session,
230230
challengeParameters = response.challengeParameters,
231231
authenticationResult = response.authenticationResult,
232+
availableChallenges = response.availableChallenges?.map { it.value },
232233
signInMethod = SignInMethod.ApiBased(SignInMethod.ApiBased.AuthType.USER_AUTH)
233234
)
234235
} else {

aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/helpers/SignInChallengeHelper.kt

Lines changed: 45 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,12 @@ import aws.sdk.kotlin.services.cognitoidentityprovider.model.ChallengeNameType
2121
import aws.smithy.kotlin.runtime.time.Instant
2222
import com.amplifyframework.auth.AuthCodeDeliveryDetails
2323
import com.amplifyframework.auth.AuthCodeDeliveryDetails.DeliveryMedium
24-
import com.amplifyframework.auth.AuthException
2524
import com.amplifyframework.auth.AuthFactorType
2625
import com.amplifyframework.auth.MFAType
27-
import com.amplifyframework.auth.TOTPSetupDetails
26+
import com.amplifyframework.auth.cognito.helpers.UserPoolSignInHelper.signInResult
2827
import com.amplifyframework.auth.exceptions.UnknownException
2928
import com.amplifyframework.auth.result.AuthSignInResult
30-
import com.amplifyframework.auth.result.step.AuthNextSignInStep
3129
import com.amplifyframework.auth.result.step.AuthSignInStep
32-
import com.amplifyframework.core.Consumer
3330
import com.amplifyframework.statemachine.StateMachineEvent
3431
import com.amplifyframework.statemachine.codegen.data.AuthChallenge
3532
import com.amplifyframework.statemachine.codegen.data.ChallengeParameter
@@ -145,171 +142,73 @@ internal object SignInChallengeHelper {
145142
else -> SignInEvent(SignInEvent.EventType.ThrowError(Exception("Response did not contain sign in info.")))
146143
}
147144

148-
fun getNextStep(
149-
challenge: AuthChallenge,
150-
onSuccess: Consumer<AuthSignInResult>,
151-
onError: Consumer<AuthException>,
152-
signInTOTPSetupData: SignInTOTPSetupData? = null,
153-
allowedMFAType: Set<MFAType>? = null
154-
) {
145+
fun getNextStep(challenge: AuthChallenge): AuthSignInResult {
155146
val challengeParams = challenge.parameters ?: emptyMap()
156-
157-
when (challenge.challengeNameType) {
158-
is ChallengeNameType.SmsMfa,
159-
ChallengeNameType.EmailOtp,
160-
ChallengeNameType.SmsOtp -> {
161-
val deliveryDetails = AuthCodeDeliveryDetails(
147+
return when (challenge.challengeNameType) {
148+
ChallengeNameType.SmsMfa -> signInResult(
149+
signInStep = AuthSignInStep.CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE,
150+
codeDeliveryDetails = AuthCodeDeliveryDetails(
162151
challengeParams.getValue(ChallengeParameter.CodeDeliveryDestination.key),
163152
DeliveryMedium.fromString(challengeParams.getValue(ChallengeParameter.CodeDeliveryMedium.key))
164153
)
165-
val signInStep = if (challenge.challengeNameType == ChallengeNameType.SmsMfa) {
166-
AuthSignInStep.CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE
167-
} else {
168-
AuthSignInStep.CONFIRM_SIGN_IN_WITH_OTP
169-
}
170-
val authSignInResult = AuthSignInResult(
171-
false,
172-
AuthNextSignInStep(
173-
signInStep,
174-
mapOf(),
175-
deliveryDetails,
176-
null,
177-
null,
178-
null
179-
)
180-
)
181-
onSuccess.accept(authSignInResult)
182-
}
183-
is ChallengeNameType.NewPasswordRequired -> {
184-
val authSignInResult = AuthSignInResult(
185-
false,
186-
AuthNextSignInStep(
187-
AuthSignInStep.CONFIRM_SIGN_IN_WITH_NEW_PASSWORD,
188-
challengeParams,
189-
null,
190-
null,
191-
null,
192-
null
193-
)
194-
)
195-
onSuccess.accept(authSignInResult)
196-
}
197-
is ChallengeNameType.CustomChallenge -> {
198-
val authSignInResult = AuthSignInResult(
199-
false,
200-
AuthNextSignInStep(
201-
AuthSignInStep.CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE,
202-
challengeParams,
203-
null,
204-
null,
205-
null,
206-
null
207-
)
208-
)
209-
onSuccess.accept(authSignInResult)
210-
}
211-
is ChallengeNameType.SoftwareTokenMfa -> {
212-
val authSignInResult = AuthSignInResult(
213-
false,
214-
AuthNextSignInStep(
215-
AuthSignInStep.CONFIRM_SIGN_IN_WITH_TOTP_CODE,
216-
emptyMap(),
217-
null,
218-
null,
219-
null,
220-
null
221-
)
154+
)
155+
ChallengeNameType.EmailOtp, ChallengeNameType.SmsOtp -> signInResult(
156+
signInStep = AuthSignInStep.CONFIRM_SIGN_IN_WITH_OTP,
157+
codeDeliveryDetails = AuthCodeDeliveryDetails(
158+
challengeParams.getValue(ChallengeParameter.CodeDeliveryDestination.key),
159+
DeliveryMedium.fromString(challengeParams.getValue(ChallengeParameter.CodeDeliveryMedium.key))
222160
)
223-
onSuccess.accept(authSignInResult)
224-
}
225-
is ChallengeNameType.MfaSetup -> {
161+
)
162+
ChallengeNameType.NewPasswordRequired -> signInResult(
163+
signInStep = AuthSignInStep.CONFIRM_SIGN_IN_WITH_NEW_PASSWORD
164+
)
165+
ChallengeNameType.CustomChallenge -> signInResult(
166+
signInStep = AuthSignInStep.CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE,
167+
additionalInfo = challengeParams
168+
)
169+
ChallengeNameType.SoftwareTokenMfa -> signInResult(
170+
signInStep = AuthSignInStep.CONFIRM_SIGN_IN_WITH_TOTP_CODE
171+
)
172+
ChallengeNameType.MfaSetup -> {
226173
val allowedMFASetupTypes = getAllowedMFASetupTypesFromChallengeParameters(challengeParams)
227-
228174
if (allowedMFASetupTypes.contains(MFAType.TOTP) && allowedMFASetupTypes.contains(MFAType.EMAIL)) {
229-
val authSignInResult = AuthSignInResult(
230-
false,
231-
AuthNextSignInStep(
232-
AuthSignInStep.CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION,
233-
emptyMap(),
234-
null,
235-
null,
236-
allowedMFASetupTypes,
237-
null
238-
)
175+
signInResult(
176+
signInStep = AuthSignInStep.CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION,
177+
allowedMFATypes = allowedMFASetupTypes
239178
)
240-
onSuccess.accept(authSignInResult)
241-
} else if (allowedMFASetupTypes.contains(MFAType.TOTP) && signInTOTPSetupData != null) {
242-
val authSignInResult = AuthSignInResult(
243-
false,
244-
AuthNextSignInStep(
245-
AuthSignInStep.CONTINUE_SIGN_IN_WITH_TOTP_SETUP,
246-
challengeParams,
247-
null,
248-
TOTPSetupDetails(signInTOTPSetupData.secretCode, signInTOTPSetupData.username),
249-
allowedMFAType,
250-
null
251-
)
252-
)
253-
onSuccess.accept(authSignInResult)
254179
} else if (allowedMFASetupTypes.contains(MFAType.EMAIL)) {
255-
val authSignInResult = AuthSignInResult(
256-
false,
257-
AuthNextSignInStep(
258-
AuthSignInStep.CONTINUE_SIGN_IN_WITH_EMAIL_MFA_SETUP,
259-
emptyMap(),
260-
null,
261-
null,
262-
allowedMFAType,
263-
null
264-
)
265-
)
266-
onSuccess.accept(authSignInResult)
180+
signInResult(signInStep = AuthSignInStep.CONTINUE_SIGN_IN_WITH_EMAIL_MFA_SETUP)
267181
} else {
268-
onError.accept(UnknownException(cause = Exception("Challenge type not supported.")))
182+
unknownException("Unsupported MFA type")
269183
}
270184
}
271-
is ChallengeNameType.SelectMfaType -> {
272-
val authSignInResult = AuthSignInResult(
273-
false,
274-
AuthNextSignInStep(
275-
AuthSignInStep.CONTINUE_SIGN_IN_WITH_MFA_SELECTION,
276-
mapOf(),
277-
null,
278-
null,
279-
getAllowedMFATypesFromChallengeParameters(challengeParams),
280-
null
281-
)
282-
)
283-
onSuccess.accept(authSignInResult)
284-
}
285-
is ChallengeNameType.SelectChallenge -> {
286-
val authSignInResult = AuthSignInResult(
287-
false,
288-
AuthNextSignInStep(
289-
AuthSignInStep.CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION,
290-
mapOf(),
291-
null,
292-
null,
293-
null,
294-
getAvailableFactors(challenge.availableChallenges)
295-
)
296-
)
297-
onSuccess.accept(authSignInResult)
298-
}
299-
else -> onError.accept(UnknownException(cause = Exception("Challenge type not supported.")))
185+
ChallengeNameType.SelectMfaType -> signInResult(
186+
signInStep = AuthSignInStep.CONTINUE_SIGN_IN_WITH_MFA_SELECTION,
187+
allowedMFATypes = getAllowedMFATypesFromChallengeParameters(challengeParams)
188+
)
189+
ChallengeNameType.SelectChallenge -> signInResult(
190+
signInStep = AuthSignInStep.CONTINUE_SIGN_IN_WITH_FIRST_FACTOR_SELECTION,
191+
availableFactors = getAvailableFactors(challenge.availableChallenges)
192+
)
193+
ChallengeNameType.Password, ChallengeNameType.PasswordSrp -> signInResult(
194+
signInStep = AuthSignInStep.CONFIRM_SIGN_IN_WITH_PASSWORD
195+
)
196+
else -> unknownException("Challenge type not supported.")
300197
}
301198
}
302199

200+
private fun unknownException(message: String): Nothing = throw UnknownException(message = message)
201+
303202
private fun getAvailableFactors(possibleFactors: List<String>?): Set<AuthFactorType> {
304203
val result = mutableSetOf<AuthFactorType>()
305204
if (possibleFactors == null) {
306-
throw UnknownException(cause = Exception("Tried to parse available factors but found none."))
205+
unknownException("Tried to parse available factors but found none.")
307206
} else {
308207
possibleFactors.forEach {
309208
try {
310209
result.add(AuthFactorType.valueOf(it))
311210
} catch (exception: IllegalArgumentException) {
312-
throw UnknownException(cause = Exception("Tried to parse an unrecognized AuthFactorType"))
211+
unknownException("Tried to parse an unrecognized AuthFactorType")
313212
}
314213
}
315214
}

0 commit comments

Comments
 (0)