Skip to content

trying out ui tests #97

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/ui_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Run UI Tests

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
ui-test-ios:
runs-on: macos-15
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
- name: UI test Authenticator on iOS
working-directory: Tests/AuthenticatorHostApp
run: 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]}
16 changes: 8 additions & 8 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ let package = Package(
targets: ["Authenticator"]),
],
dependencies: [
.package(url: "https://github.com/aws-amplify/amplify-swift", from: "2.35.0"),
.package(url: "https://github.com/aws-amplify/amplify-swift", branch: "feat/email-mfa-support-public"),
],
targets: [
.target(
Expand Down
51 changes: 45 additions & 6 deletions Sources/Authenticator/Authenticator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ public struct Authenticator<LoadingContent: View,
SignInContent: View,
ConfirmSignInWithNewPasswordContent: View,
ConfirmSignInWithMFACodeContent: View,
ConfirmSignInWithOTPContent: View,
ConfirmSignInWithTOTPCodeContent: View,
ContinueSignInWithMFASelectionContent: View,
ContinueSignInWithMFASetupSelectionContent: View,
ContinueSignInWithEmailMFASetupContent: View,
ContinueSignInWithTOTPSetupContent: View,
ConfirmSignInWithCustomChallengeContent: View,
SignUpContent: View,
Expand All @@ -37,10 +40,13 @@ public struct Authenticator<LoadingContent: View,
private var contentStates: NSHashTable<AuthenticatorBaseState> = .weakObjects()
private let loadingContent: LoadingContent
private let signInContent: SignInContent
private let confirmSignInContentWithMFACodeContent: ConfirmSignInWithMFACodeContent
private let confirmSignInWithMFACodeContent: ConfirmSignInWithMFACodeContent
private let confirmSignInWithOTPContent: (ConfirmSignInWithCodeState) -> ConfirmSignInWithOTPContent
private let confirmSignInWithTOTPCodeContent: (ConfirmSignInWithCodeState) -> ConfirmSignInWithTOTPCodeContent
private let continueSignInWithMFASelectionContent: (ContinueSignInWithMFASelectionState) -> ContinueSignInWithMFASelectionContent
private let continueSignInWithMFASetupSelectionContent: (ContinueSignInWithMFASetupSelectionState) -> ContinueSignInWithMFASetupSelectionContent
private let continueSignInWithTOTPSetupContent: (ContinueSignInWithTOTPSetupState) -> ContinueSignInWithTOTPSetupContent
private let continueSignInWithEmailMFASetupContent: (ContinueSignInWithEmailMFASetupState) -> ContinueSignInWithEmailMFASetupContent
private let confirmSignInContentWithCustomChallengeContent: ConfirmSignInWithCustomChallengeContent
private let confirmSignInContentWithNewPasswordContent: ConfirmSignInWithNewPasswordContent
private let signUpContent: SignUpContent
Expand All @@ -65,12 +71,18 @@ public struct Authenticator<LoadingContent: View,
/// Defaults to a ``SignInView``.
/// - Parameter confirmSignInWithMFACodeContent: The content associated with the ``AuthenticatorStep/confirmSignInWithMFACode`` step.
/// Defaults to a ``ConfirmSignInWithMFACodeView``.
/// - Parameter confirmSignInWithOTPContent: The content associated with the ``AuthenticatorStep/confirmSignInWithOTP`` step.
/// Defaults to a ``ConfirmSignInWithOTPView``.
///- Parameter confirmSignInWithTOTPCodeContent: The content associated with the ``AuthenticatorStep/confirmSignInWithTOTPCode`` step.
/// Defaults to a ``ConfirmSignInWithMFACodeView``.
///- Parameter continueSignInWithMFASelectionContent: The content associated with the ``AuthenticatorStep/continueSignInWithMFASelection`` step.
/// Defaults to a ``ContinueSignInWithMFASelectionView``.
///- Parameter continueSignInWithMFASetupSelectionContent: The content associated with the ``AuthenticatorStep/continueSignInWithMFASetupSelection`` step.
/// Defaults to a ``ContinueSignInWithMFASetupSelectionView``.
///- Parameter continueSignInWithTOTPSetupContent: The content associated with the ``AuthenticatorStep/continueSignInWithTOTPSetup`` step.
/// Defaults to a ``ContinueSignInWithTOTPSetupView``.
///- Parameter continueSignInWithEmailMFASetupContent: The content associated with the ``AuthenticatorStep/continueSignInWithEmailMFASetup`` step.
/// Defaults to a ``ContinueSignInWithEmailMFASetupView``.
/// - Parameter confirmSignInWithCustomChallengeContent: The content associated with the ``AuthenticatorStep/confirmSignInWithCustomChallenge`` step.
/// Defaults to a ``ConfirmSignInWithCustomChallengeView``.
/// - Parameter confirmSignInWithNewPasswordContent: The content associated with the ``AuthenticatorStep/confirmSignInWithNewPassword`` step.
Expand Down Expand Up @@ -106,15 +118,24 @@ public struct Authenticator<LoadingContent: View,
@ViewBuilder confirmSignInWithMFACodeContent: (ConfirmSignInWithCodeState) -> ConfirmSignInWithMFACodeContent = { state in
ConfirmSignInWithMFACodeView(state: state)
},
@ViewBuilder confirmSignInWithOTPContent: @escaping (ConfirmSignInWithCodeState) -> ConfirmSignInWithOTPContent = { state in
ConfirmSignInWithOTPView(state: state)
},
@ViewBuilder confirmSignInWithTOTPCodeContent: @escaping (ConfirmSignInWithCodeState) -> ConfirmSignInWithTOTPCodeContent = { state in
ConfirmSignInWithTOTPView(state: state)
},
@ViewBuilder continueSignInWithMFASelectionContent: @escaping (ContinueSignInWithMFASelectionState) -> ContinueSignInWithMFASelectionContent = { state in
ContinueSignInWithMFASelectionView(state: state)
},
@ViewBuilder continueSignInWithMFASetupSelectionContent: @escaping (ContinueSignInWithMFASetupSelectionState) -> ContinueSignInWithMFASetupSelectionContent = { state in
ContinueSignInWithMFASetupSelectionView(state: state)
},
@ViewBuilder continueSignInWithTOTPSetupContent: @escaping (ContinueSignInWithTOTPSetupState) -> ContinueSignInWithTOTPSetupContent = { state in
ContinueSignInWithTOTPSetupView(state: state)
},
@ViewBuilder continueSignInWithEmailMFASetupContent: @escaping (ContinueSignInWithEmailMFASetupState) -> ContinueSignInWithEmailMFASetupContent = { state in
ContinueSignInWithEmailMFASetupView(state: state)
},
@ViewBuilder confirmSignInWithCustomChallengeContent: (ConfirmSignInWithCodeState) -> ConfirmSignInWithCustomChallengeContent = { state in
ConfirmSignInWithCustomChallengeView(state: state)
},
Expand Down Expand Up @@ -157,13 +178,15 @@ public struct Authenticator<LoadingContent: View,

let confirmSignInWithMFACodeState = ConfirmSignInWithCodeState(credentials: credentials)
contentStates.add(confirmSignInWithMFACodeState)
self.confirmSignInContentWithMFACodeContent = confirmSignInWithMFACodeContent(
self.confirmSignInWithMFACodeContent = confirmSignInWithMFACodeContent(
confirmSignInWithMFACodeState
)

self.confirmSignInWithOTPContent = confirmSignInWithOTPContent
self.confirmSignInWithTOTPCodeContent = confirmSignInWithTOTPCodeContent
self.continueSignInWithMFASelectionContent = continueSignInWithMFASelectionContent
self.continueSignInWithMFASetupSelectionContent = continueSignInWithMFASetupSelectionContent
self.continueSignInWithTOTPSetupContent = continueSignInWithTOTPSetupContent
self.continueSignInWithEmailMFASetupContent = continueSignInWithEmailMFASetupContent

let confirmSignInWithCustomChallengeState = ConfirmSignInWithCodeState(credentials: credentials)
contentStates.add(confirmSignInWithMFACodeState)
Expand Down Expand Up @@ -337,25 +360,41 @@ public struct Authenticator<LoadingContent: View,
case .confirmSignInWithNewPassword:
confirmSignInContentWithNewPasswordContent
case .confirmSignInWithMFACode:
confirmSignInContentWithMFACodeContent
confirmSignInWithMFACodeContent
case .confirmSignInWithOTP(let deliveryDetails):
let confirmSignInWithCodeState = ConfirmSignInWithCodeState(
authenticatorState: state
)
confirmSignInWithOTPContent(confirmSignInWithCodeState)
case .continueSignInWithMFASelection(let allowedMFATypes):
let continueSignInWithMFASelection = ContinueSignInWithMFASelectionState(
authenticatorState: state,
allowedMFATypes: allowedMFATypes
)
continueSignInWithMFASelectionContent(continueSignInWithMFASelection)
case .continueSignInWithMFASetupSelection(let allowedMFATypes):
let continueSignInWithMFASetupSelection = ContinueSignInWithMFASetupSelectionState(
authenticatorState: state,
allowedMFATypes: allowedMFATypes
)
continueSignInWithMFASetupSelectionContent(continueSignInWithMFASetupSelection)
case .confirmSignInWithTOTPCode:
let confirmSignInWithCodeState = ConfirmSignInWithCodeState(
authenticatorState: state
)
confirmSignInWithTOTPCodeContent(confirmSignInWithCodeState)
case .continueSignInWithTOTPSetup(let totpSetupDetails):
let totpStupState = ContinueSignInWithTOTPSetupState(
let totpSetupState = ContinueSignInWithTOTPSetupState(
authenticatorState: state,
issuer: totpOptions.issuer,
totpSetupDetails: totpSetupDetails
)
continueSignInWithTOTPSetupContent(totpStupState)
continueSignInWithTOTPSetupContent(totpSetupState)
case .continueSignInWithEmailMFASetup:
let emailMFASetupState = ContinueSignInWithEmailMFASetupState(
authenticatorState: state
)
continueSignInWithEmailMFASetupContent(emailMFASetupState)
case .confirmSignInWithCustomChallenge:
confirmSignInContentWithCustomChallengeContent
case .resetPassword:
Expand Down
14 changes: 13 additions & 1 deletion Sources/Authenticator/Models/AuthenticatorStep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,26 @@ public struct AuthenticatorStep: Equatable {
/// so they are presented with the TOTP Setup View
public static let continueSignInWithTOTPSetup = AuthenticatorStep("continueSignInWithTOTPSetup")

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

/// A user has successfully provided valid Sign In credentials but is required to select a MFA type to setup before completing sign in
/// so they are presented with the Confirm Sign In with MFA Setup Selection View
public static let continueSignInWithMFASetupSelection = AuthenticatorStep("continueSignInWithMFASetupSelection")

/// A user has successfully provided valid Sign In credentials but is required to setup Email MFA before continuing sign in
/// so they are presented with the Email Setup View
public static let continueSignInWithEmailMFASetup = AuthenticatorStep("continueSignInWithEmailMFASetup")

/// A user has successfully provided valid Sign In credentials but is required to provide a MFA code,
/// so they are presented with the Confirm Sign In with MFA Code view
public static let confirmSignInWithMFACode = AuthenticatorStep("confirmSignInWithMFACode")

/// A user has successfully provided valid Sign In credentials but is required to provide a OTP,
/// so they are presented with the Confirm Sign In with OTP view
public static let confirmSignInWithOTP = AuthenticatorStep("confirmSignInWithOTP")

/// A user has successfully provided valid Sign In credentials but is required to change their password,
/// so they are presented with the Confirm Sign In with New Password view
public static let confirmSignInWithNewPassword = AuthenticatorStep("confirmSignInWithNewPassword")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
// SPDX-License-Identifier: Apache-2.0
//

enum AuthenticatorMFAType {
enum AuthenticatorFactorType {
case sms
case email
case totp
case none
}
9 changes: 9 additions & 0 deletions Sources/Authenticator/Models/Internal/Step.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ enum Step {
case confirmSignInWithCustomChallenge
case confirmSignInWithTOTPCode
case continueSignInWithMFASelection(allowedMFATypes: AllowedMFATypes)
case continueSignInWithMFASetupSelection(allowedMFATypes: AllowedMFATypes)
case continueSignInWithEmailMFASetup
case continueSignInWithTOTPSetup(totpSetupDetails: TOTPSetupDetails)
case confirmSignInWithMFACode(deliveryDetails: AuthCodeDeliveryDetails?)
case confirmSignInWithOTP(deliveryDetails: AuthCodeDeliveryDetails?)
case confirmSignInWithNewPassword
case signUp
case confirmSignUp(deliveryDetails: AuthCodeDeliveryDetails?)
Expand Down Expand Up @@ -55,8 +58,14 @@ enum Step {
return .continueSignInWithTOTPSetup
case .continueSignInWithMFASelection:
return .continueSignInWithMFASelection
case .continueSignInWithMFASetupSelection:
return .continueSignInWithMFASetupSelection
case .continueSignInWithEmailMFASetup:
return .continueSignInWithEmailMFASetup
case .confirmSignInWithMFACode:
return .confirmSignInWithMFACode
case .confirmSignInWithOTP:
return .confirmSignInWithOTP
case .confirmSignInWithNewPassword:
return .confirmSignInWithNewPassword
case .signUp:
Expand Down
33 changes: 26 additions & 7 deletions Sources/Authenticator/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,11 @@
"authenticator.confirmSignInWithNewPassword.title" = "Set a new password";
"authenticator.confirmSignInWithNewPassword.button.submit" = "Submit";

/* Confirm Sign In with OTP view */
"authenticator.confirmSignInWithOTP.title" = "Verify your sign-in";

/* Confirm Sign In with MFA view */
"authenticator.confirmSignInWithMFACode.title" = "Enter your Sign In code";
"authenticator.confirmSignInWithMFACode.title" = "Verify your sign-in";

/* Confirm Sign In with Custom Challenge view */
"authenticator.confirmSignInWithCustomChallenge.title" = "Enter your Sign In code";
Expand All @@ -85,10 +88,26 @@
"authenticator.confirmSignInWithCode.totp.button.submit" = "Confirm";
"authenticator.confirmSignInWithCode.totp.button.backToSignIn" = "Back to Sign In";

/* Continue Sign In with MFA Setup Selection */
"authenticator.continueSignInWithMFASetupSelection.email.radioButton.title" = "Email Message";
"authenticator.continueSignInWithMFASetupSelection.totp.radioButton.title" = "Authenticator App (TOTP)";
"authenticator.continueSignInWithMFASetupSelection.button.continue" = "Continue";
"authenticator.continueSignInWithMFASetupSelection.title" = "Choose your preferred two-factor authentication method to set up";
"authenticator.continueSignInWithMFASetupSelection.body" = "Select your preferred way to verify your identity when using two-factor authentication (2FA). This will be your default method for added account security.";
"authenticator.continueSignInWithMFASetupSelection.button.backToSignIn" = "Back to Sign In";

/* Continue Sign In with Email MFA Setup */
"authenticator.continueSignInWithEmailMFASetup.title" = "Add Email for Two-Factor Authentication";
"authenticator.continueSignInWithEmailMFASetup.button.continue" = "Continue";
"authenticator.continueSignInWithEmailMFASetup.field.email.label" = "Enter the email address you want to use for two-factor authentication (2FA). This email will receive verification codes when you sign in";
"authenticator.continueSignInWithEmailMFASetup.button.backToSignIn" = "Back to Sign In";

/* Continue Sign In with MFA Selection */
"authenticator.continueSignInWithMFASelection.title" = "Select your preferred Two-Factor Auth method";
"authenticator.continueSignInWithMFASelection.title" = "Choose your two-factor authentication method";
"authenticator.continueSignInWithMFASelection.subtitle" = "For added security, choose how you want to verify your identity for this sign-in.";
"authenticator.continueSignInWithMFASelection.sms.radioButton.title" = "Text Message (SMS)";
"authenticator.continueSignInWithMFASelection.totp.radioButton.title" = "Authenticator App (TOTP)";
"authenticator.continueSignInWithMFASelection.email.radioButton.title" = "Email Message";
"authenticator.continueSignInWithMFASelection.button.submit" = "Continue";
"authenticator.continueSignInWithMFASelection.button.backToSignIn" = "Back to Sign In";

Expand Down Expand Up @@ -155,8 +174,8 @@
"authenticator.validator.field.phoneNumber.format" = "Invalid phone number";

/* Authenticator Banner Messages */
"authenticator.banner.sendCode" = "A confirmation code has been sent to %@"; // Argument is the destination where a code was sent. E.g. "axxx@axxx.com"
"authenticator.banner.sendCodeGeneric" = "A confirmation code has been sent";
"authenticator.banner.sendCode" = "A verification code has been sent to %@"; // Argument is the destination where a code was sent. E.g. "axxx@axxx.com"
"authenticator.banner.sendCodeGeneric" = "A verification code has been sent";

/* Authenticator Error View */
"authenticator.authenticatorError.title" = "Something went wrong";
Expand All @@ -168,9 +187,9 @@
"authenticator.authError.continueSignInWithMFASelection.noSelectionError" = "Please select an MFA method to continue";
"authenticator.unknownError" = "Sorry, something went wrong";

"authenticator.cognitoError.codeDelivery" = "Could not send confirmation code";
"authenticator.cognitoError.codeExpired" = "Confirmation code has expired";
"authenticator.cognitoError.codeMismatch" = "Incorrect confirmation code";
"authenticator.cognitoError.codeDelivery" = "Could not send verification code";
"authenticator.cognitoError.codeExpired" = "Verification code has expired";
"authenticator.cognitoError.codeMismatch" = "Incorrect verification code";
"authenticator.cognitoError.invalidPassword" = "The provided password is not valid";
"authenticator.cognitoError.network" = "Please check your connectivity";
"authenticator.cognitoError.usernameExists" = "Username already exists";
Expand Down
Loading
Loading