Skip to content

Commit 541ec6e

Browse files
harsh62sebaland
andauthored
feat: add support for email mfa (#94)
* add support for email mfa code * adding support for mfa setup selection and setting up email * Apply suggestions from code review Co-authored-by: Sebastian Villena <97059974+ruisebas@users.noreply.github.com> * worked on review comments * update strings and some logics * missed update * fix conflicts * pushing a test. * update sign in step to confirmSignInWithOTP * Update Sources/Authenticator/Views/ConfirmSignInWithOTPView.swift Co-authored-by: Sebastian Villena <97059974+ruisebas@users.noreply.github.com> * Update Sources/Authenticator/Views/ConfirmSignInWithOTPView.swift Co-authored-by: Sebastian Villena <97059974+ruisebas@users.noreply.github.com> * Update Sources/Authenticator/Views/ConfirmSignInWithOTPView.swift Co-authored-by: Sebastian Villena <97059974+ruisebas@users.noreply.github.com> * worked on review comment * updated to match Android * fix failing tests * add/update UI Tests and snapshot images * trying out ui tests * update * missing added file * adding ui tests for next steps * revert the package swift for release * Update Sources/Authenticator/Views/Internal/ConfirmSignInWithCodeView.swift * Update Sources/Authenticator/Views/Internal/ConfirmSignInWithCodeView.swift * Update Sources/Authenticator/Views/Internal/ConfirmSignInWithCodeView.swift * Update Sources/Authenticator/Views/Internal/ConfirmSignInWithCodeView.swift * update workflow to get the the latest package dependencies * update workflow * another update * update * update * update * update package.resolved to remove email mfa support branch reference * update amplify version dependency --------- Co-authored-by: Sebastian Villena <97059974+ruisebas@users.noreply.github.com>
1 parent 1ec95fb commit 541ec6e

File tree

55 files changed

+1095
-123
lines changed

Some content is hidden

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

55 files changed

+1095
-123
lines changed

.github/workflows/ui_tests.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Run UI Tests
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
ui-test-ios:
11+
runs-on: macos-15
12+
steps:
13+
- name: Checkout
14+
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
15+
16+
- name: Resolve and update Swift packages
17+
run: xcodebuild -resolvePackageDependencies -scheme Authenticator
18+
19+
- name: UI test Authenticator on iOS
20+
working-directory: Tests/AuthenticatorHostApp
21+
run: |
22+
xcodebuild -resolvePackageDependencies -scheme Authenticator
23+
xcodebuild test -scheme AuthenticatorHostApp -sdk 'iphonesimulator' -destination 'platform=iOS Simulator,name=iPhone 16 Pro Max,OS=latest' -derivedDataPath Build/ -clonedSourcePackagesDirPath ~/Library/Developer/Xcode/DerivedData/Authenticator | xcpretty --simple --color --report junit && exit ${PIPESTATUS[0]}

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@ amplifyconfiguration.dart
4848
amplify-build-config.json
4949
amplify-gradle-config.json
5050
amplifytools.xcconfig
51-
.secret-*
51+
.secret-*
52+
Tests/AuthenticatorHostApp/AuthenticatorHostApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 1.2.0 (2024-10-31)
4+
5+
### Feature
6+
- **Authenticator**: Adding support for Email MFA (#96)
7+
38
## 1.1.8 (2024-09-20)
49

510
### Bug Fixes

Package.resolved

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ let package = Package(
1313
targets: ["Authenticator"]),
1414
],
1515
dependencies: [
16-
.package(url: "https://github.com/aws-amplify/amplify-swift", from: "2.35.0"),
16+
.package(url: "https://github.com/aws-amplify/amplify-swift", from: "2.44.0"),
1717
],
1818
targets: [
1919
.target(

Sources/Authenticator/Authenticator.swift

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@ public struct Authenticator<LoadingContent: View,
1313
SignInContent: View,
1414
ConfirmSignInWithNewPasswordContent: View,
1515
ConfirmSignInWithMFACodeContent: View,
16+
ConfirmSignInWithOTPContent: View,
1617
ConfirmSignInWithTOTPCodeContent: View,
1718
ContinueSignInWithMFASelectionContent: View,
19+
ContinueSignInWithMFASetupSelectionContent: View,
20+
ContinueSignInWithEmailMFASetupContent: View,
1821
ContinueSignInWithTOTPSetupContent: View,
1922
ConfirmSignInWithCustomChallengeContent: View,
2023
SignUpContent: View,
@@ -37,10 +40,13 @@ public struct Authenticator<LoadingContent: View,
3740
private var contentStates: NSHashTable<AuthenticatorBaseState> = .weakObjects()
3841
private let loadingContent: LoadingContent
3942
private let signInContent: SignInContent
40-
private let confirmSignInContentWithMFACodeContent: ConfirmSignInWithMFACodeContent
43+
private let confirmSignInWithMFACodeContent: ConfirmSignInWithMFACodeContent
44+
private let confirmSignInWithOTPContent: (ConfirmSignInWithCodeState) -> ConfirmSignInWithOTPContent
4145
private let confirmSignInWithTOTPCodeContent: (ConfirmSignInWithCodeState) -> ConfirmSignInWithTOTPCodeContent
4246
private let continueSignInWithMFASelectionContent: (ContinueSignInWithMFASelectionState) -> ContinueSignInWithMFASelectionContent
47+
private let continueSignInWithMFASetupSelectionContent: (ContinueSignInWithMFASetupSelectionState) -> ContinueSignInWithMFASetupSelectionContent
4348
private let continueSignInWithTOTPSetupContent: (ContinueSignInWithTOTPSetupState) -> ContinueSignInWithTOTPSetupContent
49+
private let continueSignInWithEmailMFASetupContent: (ContinueSignInWithEmailMFASetupState) -> ContinueSignInWithEmailMFASetupContent
4450
private let confirmSignInContentWithCustomChallengeContent: ConfirmSignInWithCustomChallengeContent
4551
private let confirmSignInContentWithNewPasswordContent: ConfirmSignInWithNewPasswordContent
4652
private let signUpContent: SignUpContent
@@ -65,12 +71,18 @@ public struct Authenticator<LoadingContent: View,
6571
/// Defaults to a ``SignInView``.
6672
/// - Parameter confirmSignInWithMFACodeContent: The content associated with the ``AuthenticatorStep/confirmSignInWithMFACode`` step.
6773
/// Defaults to a ``ConfirmSignInWithMFACodeView``.
74+
/// - Parameter confirmSignInWithOTPContent: The content associated with the ``AuthenticatorStep/confirmSignInWithOTP`` step.
75+
/// Defaults to a ``ConfirmSignInWithOTPView``.
6876
///- Parameter confirmSignInWithTOTPCodeContent: The content associated with the ``AuthenticatorStep/confirmSignInWithTOTPCode`` step.
6977
/// Defaults to a ``ConfirmSignInWithMFACodeView``.
7078
///- Parameter continueSignInWithMFASelectionContent: The content associated with the ``AuthenticatorStep/continueSignInWithMFASelection`` step.
7179
/// Defaults to a ``ContinueSignInWithMFASelectionView``.
80+
///- Parameter continueSignInWithMFASetupSelectionContent: The content associated with the ``AuthenticatorStep/continueSignInWithMFASetupSelection`` step.
81+
/// Defaults to a ``ContinueSignInWithMFASetupSelectionView``.
7282
///- Parameter continueSignInWithTOTPSetupContent: The content associated with the ``AuthenticatorStep/continueSignInWithTOTPSetup`` step.
7383
/// Defaults to a ``ContinueSignInWithTOTPSetupView``.
84+
///- Parameter continueSignInWithEmailMFASetupContent: The content associated with the ``AuthenticatorStep/continueSignInWithEmailMFASetup`` step.
85+
/// Defaults to a ``ContinueSignInWithEmailMFASetupView``.
7486
/// - Parameter confirmSignInWithCustomChallengeContent: The content associated with the ``AuthenticatorStep/confirmSignInWithCustomChallenge`` step.
7587
/// Defaults to a ``ConfirmSignInWithCustomChallengeView``.
7688
/// - Parameter confirmSignInWithNewPasswordContent: The content associated with the ``AuthenticatorStep/confirmSignInWithNewPassword`` step.
@@ -106,15 +118,24 @@ public struct Authenticator<LoadingContent: View,
106118
@ViewBuilder confirmSignInWithMFACodeContent: (ConfirmSignInWithCodeState) -> ConfirmSignInWithMFACodeContent = { state in
107119
ConfirmSignInWithMFACodeView(state: state)
108120
},
121+
@ViewBuilder confirmSignInWithOTPContent: @escaping (ConfirmSignInWithCodeState) -> ConfirmSignInWithOTPContent = { state in
122+
ConfirmSignInWithOTPView(state: state)
123+
},
109124
@ViewBuilder confirmSignInWithTOTPCodeContent: @escaping (ConfirmSignInWithCodeState) -> ConfirmSignInWithTOTPCodeContent = { state in
110125
ConfirmSignInWithTOTPView(state: state)
111126
},
112127
@ViewBuilder continueSignInWithMFASelectionContent: @escaping (ContinueSignInWithMFASelectionState) -> ContinueSignInWithMFASelectionContent = { state in
113128
ContinueSignInWithMFASelectionView(state: state)
114129
},
130+
@ViewBuilder continueSignInWithMFASetupSelectionContent: @escaping (ContinueSignInWithMFASetupSelectionState) -> ContinueSignInWithMFASetupSelectionContent = { state in
131+
ContinueSignInWithMFASetupSelectionView(state: state)
132+
},
115133
@ViewBuilder continueSignInWithTOTPSetupContent: @escaping (ContinueSignInWithTOTPSetupState) -> ContinueSignInWithTOTPSetupContent = { state in
116134
ContinueSignInWithTOTPSetupView(state: state)
117135
},
136+
@ViewBuilder continueSignInWithEmailMFASetupContent: @escaping (ContinueSignInWithEmailMFASetupState) -> ContinueSignInWithEmailMFASetupContent = { state in
137+
ContinueSignInWithEmailMFASetupView(state: state)
138+
},
118139
@ViewBuilder confirmSignInWithCustomChallengeContent: (ConfirmSignInWithCodeState) -> ConfirmSignInWithCustomChallengeContent = { state in
119140
ConfirmSignInWithCustomChallengeView(state: state)
120141
},
@@ -157,13 +178,15 @@ public struct Authenticator<LoadingContent: View,
157178

158179
let confirmSignInWithMFACodeState = ConfirmSignInWithCodeState(credentials: credentials)
159180
contentStates.add(confirmSignInWithMFACodeState)
160-
self.confirmSignInContentWithMFACodeContent = confirmSignInWithMFACodeContent(
181+
self.confirmSignInWithMFACodeContent = confirmSignInWithMFACodeContent(
161182
confirmSignInWithMFACodeState
162183
)
163-
184+
self.confirmSignInWithOTPContent = confirmSignInWithOTPContent
164185
self.confirmSignInWithTOTPCodeContent = confirmSignInWithTOTPCodeContent
165186
self.continueSignInWithMFASelectionContent = continueSignInWithMFASelectionContent
187+
self.continueSignInWithMFASetupSelectionContent = continueSignInWithMFASetupSelectionContent
166188
self.continueSignInWithTOTPSetupContent = continueSignInWithTOTPSetupContent
189+
self.continueSignInWithEmailMFASetupContent = continueSignInWithEmailMFASetupContent
167190

168191
let confirmSignInWithCustomChallengeState = ConfirmSignInWithCodeState(credentials: credentials)
169192
contentStates.add(confirmSignInWithMFACodeState)
@@ -337,25 +360,41 @@ public struct Authenticator<LoadingContent: View,
337360
case .confirmSignInWithNewPassword:
338361
confirmSignInContentWithNewPasswordContent
339362
case .confirmSignInWithMFACode:
340-
confirmSignInContentWithMFACodeContent
363+
confirmSignInWithMFACodeContent
364+
case .confirmSignInWithOTP(let deliveryDetails):
365+
let confirmSignInWithCodeState = ConfirmSignInWithCodeState(
366+
authenticatorState: state
367+
)
368+
confirmSignInWithOTPContent(confirmSignInWithCodeState)
341369
case .continueSignInWithMFASelection(let allowedMFATypes):
342370
let continueSignInWithMFASelection = ContinueSignInWithMFASelectionState(
343371
authenticatorState: state,
344372
allowedMFATypes: allowedMFATypes
345373
)
346374
continueSignInWithMFASelectionContent(continueSignInWithMFASelection)
375+
case .continueSignInWithMFASetupSelection(let allowedMFATypes):
376+
let continueSignInWithMFASetupSelection = ContinueSignInWithMFASetupSelectionState(
377+
authenticatorState: state,
378+
allowedMFATypes: allowedMFATypes
379+
)
380+
continueSignInWithMFASetupSelectionContent(continueSignInWithMFASetupSelection)
347381
case .confirmSignInWithTOTPCode:
348382
let confirmSignInWithCodeState = ConfirmSignInWithCodeState(
349383
authenticatorState: state
350384
)
351385
confirmSignInWithTOTPCodeContent(confirmSignInWithCodeState)
352386
case .continueSignInWithTOTPSetup(let totpSetupDetails):
353-
let totpStupState = ContinueSignInWithTOTPSetupState(
387+
let totpSetupState = ContinueSignInWithTOTPSetupState(
354388
authenticatorState: state,
355389
issuer: totpOptions.issuer,
356390
totpSetupDetails: totpSetupDetails
357391
)
358-
continueSignInWithTOTPSetupContent(totpStupState)
392+
continueSignInWithTOTPSetupContent(totpSetupState)
393+
case .continueSignInWithEmailMFASetup:
394+
let emailMFASetupState = ContinueSignInWithEmailMFASetupState(
395+
authenticatorState: state
396+
)
397+
continueSignInWithEmailMFASetupContent(emailMFASetupState)
359398
case .confirmSignInWithCustomChallenge:
360399
confirmSignInContentWithCustomChallengeContent
361400
case .resetPassword:

Sources/Authenticator/Constants/ComponentInformation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
import Foundation
99

1010
public class ComponentInformation {
11-
public static let version = "1.1.8"
11+
public static let version = "1.2.0"
1212
public static let name = "amplify-ui-swift-authenticator"
1313
}

Sources/Authenticator/Models/AuthenticatorStep.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,26 @@ public struct AuthenticatorStep: Equatable {
5454
/// so they are presented with the TOTP Setup View
5555
public static let continueSignInWithTOTPSetup = AuthenticatorStep("continueSignInWithTOTPSetup")
5656

57-
/// A user has successfully provided valid Sign In credentials but is required to select a MFA type to continue
57+
/// A user has successfully provided valid Sign In credentials but is required to select a MFA type to continue signing in
5858
/// so they are presented with the Confirm Sign In with MFA Selection View
5959
public static let continueSignInWithMFASelection = AuthenticatorStep("continueSignInWithMFASelection")
6060

61+
/// A user has successfully provided valid Sign In credentials but is required to select a MFA type to setup before completing sign in
62+
/// so they are presented with the Confirm Sign In with MFA Setup Selection View
63+
public static let continueSignInWithMFASetupSelection = AuthenticatorStep("continueSignInWithMFASetupSelection")
64+
65+
/// A user has successfully provided valid Sign In credentials but is required to setup Email MFA before continuing sign in
66+
/// so they are presented with the Email Setup View
67+
public static let continueSignInWithEmailMFASetup = AuthenticatorStep("continueSignInWithEmailMFASetup")
68+
6169
/// A user has successfully provided valid Sign In credentials but is required to provide a MFA code,
6270
/// so they are presented with the Confirm Sign In with MFA Code view
6371
public static let confirmSignInWithMFACode = AuthenticatorStep("confirmSignInWithMFACode")
6472

73+
/// A user has successfully provided valid Sign In credentials but is required to provide a OTP,
74+
/// so they are presented with the Confirm Sign In with OTP view
75+
public static let confirmSignInWithOTP = AuthenticatorStep("confirmSignInWithOTP")
76+
6577
/// A user has successfully provided valid Sign In credentials but is required to change their password,
6678
/// so they are presented with the Confirm Sign In with New Password view
6779
public static let confirmSignInWithNewPassword = AuthenticatorStep("confirmSignInWithNewPassword")

Sources/Authenticator/Models/Internal/AuthenticatorMFAType.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
// SPDX-License-Identifier: Apache-2.0
66
//
77

8-
enum AuthenticatorMFAType {
8+
enum AuthenticatorFactorType {
99
case sms
10+
case email
1011
case totp
1112
case none
1213
}

Sources/Authenticator/Models/Internal/Step.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ enum Step {
1515
case confirmSignInWithCustomChallenge
1616
case confirmSignInWithTOTPCode
1717
case continueSignInWithMFASelection(allowedMFATypes: AllowedMFATypes)
18+
case continueSignInWithMFASetupSelection(allowedMFATypes: AllowedMFATypes)
19+
case continueSignInWithEmailMFASetup
1820
case continueSignInWithTOTPSetup(totpSetupDetails: TOTPSetupDetails)
1921
case confirmSignInWithMFACode(deliveryDetails: AuthCodeDeliveryDetails?)
22+
case confirmSignInWithOTP(deliveryDetails: AuthCodeDeliveryDetails?)
2023
case confirmSignInWithNewPassword
2124
case signUp
2225
case confirmSignUp(deliveryDetails: AuthCodeDeliveryDetails?)
@@ -55,8 +58,14 @@ enum Step {
5558
return .continueSignInWithTOTPSetup
5659
case .continueSignInWithMFASelection:
5760
return .continueSignInWithMFASelection
61+
case .continueSignInWithMFASetupSelection:
62+
return .continueSignInWithMFASetupSelection
63+
case .continueSignInWithEmailMFASetup:
64+
return .continueSignInWithEmailMFASetup
5865
case .confirmSignInWithMFACode:
5966
return .confirmSignInWithMFACode
67+
case .confirmSignInWithOTP:
68+
return .confirmSignInWithOTP
6069
case .confirmSignInWithNewPassword:
6170
return .confirmSignInWithNewPassword
6271
case .signUp:

0 commit comments

Comments
 (0)