-
Notifications
You must be signed in to change notification settings - Fork 199
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Auth): Using helpers for passwordless workflows (#3390)
* feat(Auth): Using helpers for passwordless workflows * worked on review comments
- Loading branch information
1 parent
686984c
commit 214d0a9
Showing
14 changed files
with
610 additions
and
688 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
117 changes: 117 additions & 0 deletions
117
...uth/Sources/AWSCognitoAuthPlugin/Operations/Helpers/PasswordlessConfirmSignInHelper.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
import Foundation | ||
import Amplify | ||
|
||
struct PasswordlessConfirmSignInHelper: DefaultLogger { | ||
|
||
private let authStateMachine: AuthStateMachine | ||
private let taskHelper: AWSAuthTaskHelper | ||
private let challengeResponse: String | ||
private let confirmSignInRequestMetadata: PasswordlessCustomAuthRequest | ||
private let pluginOptions: Any? | ||
|
||
init(authStateMachine: AuthStateMachine, | ||
challengeResponse: String, | ||
confirmSignInRequestMetadata: PasswordlessCustomAuthRequest, | ||
pluginOptions: Any?) { | ||
|
||
self.authStateMachine = authStateMachine | ||
self.taskHelper = AWSAuthTaskHelper(authStateMachine: authStateMachine) | ||
self.challengeResponse = challengeResponse | ||
self.confirmSignInRequestMetadata = confirmSignInRequestMetadata | ||
self.pluginOptions = pluginOptions | ||
} | ||
|
||
func confirmSignIn() async throws -> AuthSignInResult { | ||
log.verbose("Starting execution") | ||
await taskHelper.didStateMachineConfigured() | ||
|
||
let invalidStateError = AuthError.invalidState( | ||
"User is not attempting signIn operation", | ||
AuthPluginErrorConstants.invalidStateError, nil) | ||
|
||
guard case .configured(let authNState, _) = await authStateMachine.currentState, | ||
case .signingIn(let signInState) = authNState else { | ||
throw invalidStateError | ||
} | ||
|
||
guard case .resolvingChallenge(let challengeState, _, _) = signInState else { | ||
throw invalidStateError | ||
} | ||
|
||
switch challengeState { | ||
case .waitingForAnswer, .error: | ||
log.verbose("Sending confirm signIn event: \(challengeState)") | ||
await sendConfirmSignInEvent() | ||
default: | ||
throw invalidStateError | ||
} | ||
|
||
let stateSequences = await authStateMachine.listen() | ||
log.verbose("Waiting for response") | ||
for await state in stateSequences { | ||
guard case .configured(let authNState, let authZState) = state else { | ||
continue | ||
} | ||
switch authNState { | ||
case .signedIn: | ||
if case .sessionEstablished = authZState { | ||
return AuthSignInResult(nextStep: .done) | ||
} else { | ||
log.verbose("Signed In, waiting for authorization to complete") | ||
} | ||
case .error(let error): | ||
throw AuthError.unknown("Sign in reached an error state", error) | ||
|
||
case .signingIn(let signInState): | ||
guard let result = try UserPoolSignInHelper.checkNextStep(signInState) else { | ||
continue | ||
} | ||
return result | ||
case .notConfigured: | ||
throw AuthError.configuration( | ||
"UserPool configuration is missing", | ||
AuthPluginErrorConstants.configurationError) | ||
default: | ||
throw invalidStateError | ||
} | ||
} | ||
throw invalidStateError | ||
} | ||
|
||
private func sendConfirmSignInEvent() async { | ||
let event = SignInChallengeEvent( | ||
eventType: .verifyChallengeAnswer(createConfirmSignInEventData())) | ||
await authStateMachine.send(event) | ||
} | ||
|
||
private func createConfirmSignInEventData() -> ConfirmSignInEventData { | ||
var passwordlessMetadata = confirmSignInRequestMetadata.toDictionary() | ||
if let customerMetadata = (pluginOptions as? AWSAuthConfirmSignInWithOTPOptions)?.metadata { | ||
passwordlessMetadata.merge(customerMetadata, uniquingKeysWith: { passwordlessMetadata, customerMetadata in | ||
// Ideally key collision won't happen, because passwordless has been namespaced | ||
// if for some reason collision still happens, | ||
// prioritizing passwordlessFlow keys for flow to continue without any issues. | ||
passwordlessMetadata | ||
|
||
}) | ||
} else if let customerMetadata = (pluginOptions as? AWSAuthConfirmSignInWithMagicLinkOptions)?.metadata { | ||
passwordlessMetadata.merge(customerMetadata, uniquingKeysWith: { passwordlessMetadata, customerMetadata in | ||
// Ideally key collision won't happen, because passwordless has been namespaced | ||
// if for some reason collision still happens, | ||
// prioritizing passwordlessFlow keys for flow to continue without any issues. | ||
passwordlessMetadata | ||
|
||
}) | ||
} | ||
return ConfirmSignInEventData( | ||
answer: challengeResponse, | ||
metadata: passwordlessMetadata) | ||
} | ||
} |
Oops, something went wrong.