Skip to content

Commit 7ed0d42

Browse files
committed
Add support for auto-sign-in
1 parent 6b2149b commit 7ed0d42

File tree

3 files changed

+59
-18
lines changed

3 files changed

+59
-18
lines changed

authenticator/src/main/java/com/amplifyframework/ui/authenticator/AuthenticatorViewModel.kt

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,8 @@ import kotlinx.coroutines.launch
9090
import kotlinx.coroutines.withContext
9191
import org.jetbrains.annotations.VisibleForTesting
9292

93-
internal class AuthenticatorViewModel(
94-
application: Application,
95-
private val authProvider: AuthProvider
96-
) : AndroidViewModel(application) {
93+
internal class AuthenticatorViewModel(application: Application, private val authProvider: AuthProvider) :
94+
AndroidViewModel(application) {
9795

9896
// Constructor for compose viewModels provider
9997
constructor(application: Application) : this(application, RealAuthProvider())
@@ -185,7 +183,8 @@ internal class AuthenticatorViewModel(
185183

186184
//region SignUp
187185

188-
private suspend fun signUp(username: String, password: String, attributes: List<AuthUserAttribute>) {
186+
@VisibleForTesting
187+
suspend fun signUp(username: String, password: String, attributes: List<AuthUserAttribute>) {
189188
viewModelScope.launch {
190189
val options = AuthSignUpOptions.builder().userAttributes(attributes).build()
191190

@@ -229,6 +228,7 @@ internal class AuthenticatorViewModel(
229228
moveTo(newState)
230229
}
231230
AuthSignUpStep.DONE -> handleSignedUp(username, password)
231+
AuthSignUpStep.COMPLETE_AUTO_SIGN_IN -> handleAutoSignIn(username, password)
232232
else -> {
233233
// Generic error for any other next steps that may be added in the future
234234
val exception = AuthException(
@@ -241,6 +241,18 @@ internal class AuthenticatorViewModel(
241241
}
242242
}
243243

244+
private suspend fun handleAutoSignIn(username: String, password: String) {
245+
when (val result = authProvider.autoSignIn()) {
246+
is AmplifyResult.Error -> {
247+
// If auto sign in fails then proceed with manually trying to sign in the user. If this also fails the
248+
// user will end up back on the sign in screen.
249+
logger.warn("Unable to complete auto-signIn")
250+
handleSignedUp(username, password)
251+
}
252+
is AmplifyResult.Success -> handleSignInSuccess(username, password, result.data)
253+
}
254+
}
255+
244256
private suspend fun handleSignedUp(username: String, password: String) {
245257
when (val result = authProvider.signIn(username, password)) {
246258
is AmplifyResult.Error -> {
@@ -355,22 +367,15 @@ internal class AuthenticatorViewModel(
355367
)
356368
}
357369

358-
private suspend fun handleEmailMfaSetupRequired(
359-
username: String,
360-
password: String
361-
) {
370+
private suspend fun handleEmailMfaSetupRequired(username: String, password: String) {
362371
moveTo(
363372
stateFactory.newSignInContinueWithEmailSetupState(
364373
onSubmit = { mfaType -> confirmSignIn(username, password, mfaType) }
365374
)
366375
)
367376
}
368377

369-
private suspend fun handleMfaSelectionRequired(
370-
username: String,
371-
password: String,
372-
allowedMfaTypes: Set<MFAType>?
373-
) {
378+
private suspend fun handleMfaSelectionRequired(username: String, password: String, allowedMfaTypes: Set<MFAType>?) {
374379
if (allowedMfaTypes.isNullOrEmpty()) {
375380
handleGeneralFailure(AuthException("Missing allowedMfaTypes", "Please open a bug with Amplify"))
376381
return
@@ -492,10 +497,7 @@ internal class AuthenticatorViewModel(
492497
}.join()
493498
}
494499

495-
private suspend fun handleResetPasswordSuccess(
496-
username: String,
497-
result: AuthResetPasswordResult
498-
) {
500+
private suspend fun handleResetPasswordSuccess(username: String, result: AuthResetPasswordResult) {
499501
when (result.nextStep.resetPasswordStep) {
500502
AuthResetPasswordStep.DONE -> handlePasswordResetComplete()
501503
AuthResetPasswordStep.CONFIRM_RESET_PASSWORD_WITH_CODE -> {

authenticator/src/test/java/com/amplifyframework/ui/authenticator/AuthenticatorViewModelTest.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import com.amplifyframework.auth.result.AuthResetPasswordResult
2727
import com.amplifyframework.auth.result.step.AuthNextResetPasswordStep
2828
import com.amplifyframework.auth.result.step.AuthResetPasswordStep
2929
import com.amplifyframework.auth.result.step.AuthSignInStep
30+
import com.amplifyframework.auth.result.step.AuthSignUpStep
3031
import com.amplifyframework.ui.authenticator.auth.VerificationMechanism
3132
import com.amplifyframework.ui.authenticator.enums.AuthenticatorStep
3233
import com.amplifyframework.ui.authenticator.util.AmplifyResult
@@ -440,6 +441,22 @@ class AuthenticatorViewModelTest {
440441
viewModel.currentStep shouldBe AuthenticatorStep.SignIn
441442
}
442443

444+
//endregion
445+
//region sign up tests
446+
447+
@Test
448+
fun `user can autoSignIn after sign up`() = runTest {
449+
val result = mockSignUpResult(nextStep = mockNextSignUpStep(signUpStep = AuthSignUpStep.COMPLETE_AUTO_SIGN_IN))
450+
coEvery { authProvider.signUp("username", "password", any()) } returns Success(result)
451+
coEvery { authProvider.autoSignIn() } returns Success(mockSignInResult())
452+
453+
viewModel.start(mockAuthenticatorConfiguration())
454+
viewModel.signUp("username", "password", emptyList())
455+
advanceUntilIdle()
456+
457+
viewModel.currentStep shouldBe AuthenticatorStep.SignedIn
458+
}
459+
443460
//endregion
444461
//region password reset tests
445462

authenticator/src/test/java/com/amplifyframework/ui/authenticator/MockAuthenticatorData.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ import com.amplifyframework.auth.AuthUserAttributeKey
2525
import com.amplifyframework.auth.MFAType
2626
import com.amplifyframework.auth.TOTPSetupDetails
2727
import com.amplifyframework.auth.result.AuthSignInResult
28+
import com.amplifyframework.auth.result.AuthSignUpResult
2829
import com.amplifyframework.auth.result.step.AuthNextSignInStep
30+
import com.amplifyframework.auth.result.step.AuthNextSignUpStep
2931
import com.amplifyframework.auth.result.step.AuthSignInStep
32+
import com.amplifyframework.auth.result.step.AuthSignUpStep
3033
import com.amplifyframework.ui.authenticator.auth.AmplifyAuthConfiguration
3134
import com.amplifyframework.ui.authenticator.auth.PasswordCriteria
3235
import com.amplifyframework.ui.authenticator.auth.SignInMethod
@@ -112,6 +115,25 @@ internal fun mockNextSignInStep(
112115
availableFactors
113116
)
114117

118+
internal fun mockSignUpResult(
119+
nextStep: AuthNextSignUpStep,
120+
userId: String = "userId"
121+
) = AuthSignUpResult(
122+
nextStep.signUpStep != AuthSignUpStep.CONFIRM_SIGN_UP_STEP,
123+
nextStep,
124+
userId
125+
)
126+
127+
internal fun mockNextSignUpStep(
128+
signUpStep: AuthSignUpStep = AuthSignUpStep.DONE,
129+
additionalInfo: Map<String, String> = emptyMap(),
130+
codeDeliveryDetails: AuthCodeDeliveryDetails? = null
131+
) = AuthNextSignUpStep(
132+
signUpStep,
133+
additionalInfo,
134+
codeDeliveryDetails
135+
)
136+
115137
internal fun mockUserAttributes(vararg attribute: Pair<AuthUserAttributeKey, String>) =
116138
attribute.map { AuthUserAttribute(it.first, it.second) }
117139

0 commit comments

Comments
 (0)