Skip to content

Commit 32b41d5

Browse files
authored
feat(authenticator): Add support for TOTP to Authenticator (#114)
1 parent 0314458 commit 32b41d5

File tree

48 files changed

+1433
-41
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1433
-41
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package com.amplifyframework.ui.authenticator.ui
17+
18+
import com.amplifyframework.ui.authenticator.ScreenshotTestBase
19+
import com.amplifyframework.ui.authenticator.SignInConfirmTotpCodeState
20+
import com.amplifyframework.ui.authenticator.enums.AuthenticatorInitialStep
21+
import com.amplifyframework.ui.authenticator.enums.AuthenticatorStep
22+
import com.amplifyframework.ui.authenticator.forms.FieldConfig
23+
import com.amplifyframework.ui.authenticator.forms.FieldError
24+
import com.amplifyframework.ui.authenticator.forms.FieldKey
25+
import com.amplifyframework.ui.authenticator.mockFieldData
26+
import com.amplifyframework.ui.authenticator.mockFieldState
27+
import com.amplifyframework.ui.authenticator.mockForm
28+
import org.junit.Test
29+
30+
class SignInConfirmTotpCodeScreenshots : ScreenshotTestBase() {
31+
32+
@Test
33+
fun default_state() {
34+
screenshot {
35+
SignInConfirmTotpCode(state = mockSignInConfirmTotpCodeState())
36+
}
37+
}
38+
39+
@Test
40+
fun invalid_code() {
41+
screenshot {
42+
SignInConfirmTotpCode(
43+
state = mockSignInConfirmTotpCodeState(fieldError = FieldError.ConfirmationCodeIncorrect)
44+
)
45+
}
46+
}
47+
48+
private fun mockSignInConfirmTotpCodeState(
49+
confirmationCode: String = "",
50+
fieldError: FieldError? = null
51+
) = object : SignInConfirmTotpCodeState {
52+
override val form = mockForm(
53+
mockFieldData(
54+
config = FieldConfig.Text(FieldKey.ConfirmationCode),
55+
state = mockFieldState(content = confirmationCode, error = fieldError)
56+
)
57+
)
58+
59+
override fun moveTo(step: AuthenticatorInitialStep) {}
60+
override suspend fun confirmSignIn() {}
61+
override val step = AuthenticatorStep.SignInConfirmTotpCode
62+
}
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.amplifyframework.ui.authenticator.ui
2+
3+
import com.amplifyframework.auth.MFAType
4+
import com.amplifyframework.ui.authenticator.ScreenshotTestBase
5+
import com.amplifyframework.ui.authenticator.SignInContinueWithMfaSelectionState
6+
import com.amplifyframework.ui.authenticator.enums.AuthenticatorInitialStep
7+
import com.amplifyframework.ui.authenticator.enums.AuthenticatorStep
8+
import com.amplifyframework.ui.authenticator.forms.FieldConfig
9+
import com.amplifyframework.ui.authenticator.forms.FieldKey
10+
import com.amplifyframework.ui.authenticator.mockFieldData
11+
import com.amplifyframework.ui.authenticator.mockFieldState
12+
import com.amplifyframework.ui.authenticator.mockForm
13+
import org.junit.Test
14+
15+
class SignInContinueWithMfaSelectionScreenshots : ScreenshotTestBase() {
16+
17+
@Test
18+
fun default_state() {
19+
screenshot {
20+
SignInContinueWithMfaSelection(mockSignInContinueWithMfaSelectionState())
21+
}
22+
}
23+
24+
private fun mockSignInContinueWithMfaSelectionState() = object : SignInContinueWithMfaSelectionState {
25+
override val form = mockForm(
26+
mockFieldData(
27+
config = FieldConfig.Text(FieldKey.MfaSelection),
28+
state = mockFieldState(content = "SMS_MFA")
29+
)
30+
)
31+
override val allowedMfaTypes = MFAType.values().toSet()
32+
override fun moveTo(step: AuthenticatorInitialStep) {}
33+
override suspend fun continueSignIn() {}
34+
override val step = AuthenticatorStep.SignInContinueWithMfaSelection
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.amplifyframework.ui.authenticator.ui
2+
3+
import com.amplifyframework.ui.authenticator.ScreenshotTestBase
4+
import com.amplifyframework.ui.authenticator.SignInContinueWithTotpSetupState
5+
import com.amplifyframework.ui.authenticator.enums.AuthenticatorInitialStep
6+
import com.amplifyframework.ui.authenticator.enums.AuthenticatorStep
7+
import com.amplifyframework.ui.authenticator.forms.FieldConfig
8+
import com.amplifyframework.ui.authenticator.forms.FieldError
9+
import com.amplifyframework.ui.authenticator.forms.FieldKey
10+
import com.amplifyframework.ui.authenticator.mockFieldData
11+
import com.amplifyframework.ui.authenticator.mockFieldState
12+
import com.amplifyframework.ui.authenticator.mockForm
13+
import org.junit.Test
14+
15+
class SignInContinueWithTotpSetupScreenshots : ScreenshotTestBase() {
16+
17+
@Test
18+
fun default_state() {
19+
screenshot {
20+
SignInContinueWithTotpSetup(state = mockSignInContinueWithTotpSetupState())
21+
}
22+
}
23+
24+
@Test
25+
fun invalid_code() {
26+
screenshot {
27+
SignInContinueWithTotpSetup(
28+
state = mockSignInContinueWithTotpSetupState(
29+
confirmationCode = "123456",
30+
fieldError = FieldError.ConfirmationCodeIncorrect
31+
)
32+
)
33+
}
34+
}
35+
36+
private fun mockSignInContinueWithTotpSetupState(
37+
confirmationCode: String = "",
38+
sharedSecret: String = "secret",
39+
setupUri: String = "https://docs.amplify.aws/android/tools/libraries/",
40+
fieldError: FieldError? = null
41+
) = object : SignInContinueWithTotpSetupState {
42+
override val form = mockForm(
43+
mockFieldData(
44+
config = FieldConfig.Text(FieldKey.ConfirmationCode),
45+
state = mockFieldState(content = confirmationCode, error = fieldError)
46+
)
47+
)
48+
override val sharedSecret = sharedSecret
49+
override val setupUri = setupUri
50+
override fun moveTo(step: AuthenticatorInitialStep) {}
51+
override suspend fun continueSignIn() {}
52+
override val step = AuthenticatorStep.SignInContinueWithTotpSetup
53+
}
54+
}
Loading
Loading
Loading
Loading
Loading

authenticator/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ dependencies {
1919
implementation(libs.bundles.compose)
2020
implementation(libs.androidx.lifecycle)
2121
implementation(libs.androidx.compose.viewmodel)
22+
implementation(libs.zxing)
2223
coreLibraryDesugaring(libs.android.desugar)
2324

2425
testImplementation(projects.testing)

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ package com.amplifyframework.ui.authenticator
1717

1818
import com.amplifyframework.ui.authenticator.enums.AuthenticatorInitialStep
1919
import com.amplifyframework.ui.authenticator.forms.SignUpFormBuilder
20+
import com.amplifyframework.ui.authenticator.options.TotpOptions
2021

2122
internal data class AuthenticatorConfiguration(
2223
val initialStep: AuthenticatorInitialStep,
23-
val signUpForm: SignUpFormBuilder.() -> Unit
24+
val signUpForm: SignUpFormBuilder.() -> Unit,
25+
val totpOptions: TotpOptions?
2426
)

0 commit comments

Comments
 (0)