Skip to content

Commit

Permalink
feat(Auth): Using helpers for passwordless workflows (#3390)
Browse files Browse the repository at this point in the history
* feat(Auth): Using helpers for passwordless workflows

* worked on review comments
  • Loading branch information
harsh62 authored and thisisabhash committed Dec 13, 2023
1 parent 686984c commit 214d0a9
Show file tree
Hide file tree
Showing 14 changed files with 610 additions and 688 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ extension AWSCognitoAuthPlugin: AuthCategoryBehavior {
let request = AuthConfirmSignInWithMagicLinkRequest(
challengeResponse: challengeResponse,
options: options)
let task = AWSAuthConfirmSignInWithMagicLinkTask(
let task = try AWSAuthConfirmSignInWithMagicLinkTask(
request,
stateMachine: authStateMachine,
configuration: authConfiguration)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ enum PasswordlessCustomAuthRequestAction: String {

struct PasswordlessCustomAuthRequest {

private let namespace = "amplify.passwordless"
private let namespace = "Amplify.Passwordless"

let signInMethod: PasswordlessCustomAuthSignInMethod
let action: PasswordlessCustomAuthRequestAction
Expand Down
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)
}
}
Loading

0 comments on commit 214d0a9

Please sign in to comment.