amplify-swift/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Task/AWSAuthFederateToIdentityPo...

115 lines
4.2 KiB
Swift

//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
import Foundation
import Amplify
protocol AuthFederateToIdentityPoolTask: AmplifyAuthTask where Request == AuthFederateToIdentityPoolRequest,
Success == FederateToIdentityPoolResult,
Failure == AuthError {}
public extension HubPayload.EventName.Auth {
/// eventName for HubPayloads emitted by this operation
static let federateToIdentityPoolAPI = "Auth.federatedToIdentityPool"
}
public class AWSAuthFederateToIdentityPoolTask: AuthFederateToIdentityPoolTask {
private let request: AuthFederateToIdentityPoolRequest
private let authStateMachine: AuthStateMachine
private let taskHelper: AWSAuthTaskHelper
public var eventName: HubPayloadEventName {
HubPayload.EventName.Auth.federateToIdentityPoolAPI
}
init(_ request: AuthFederateToIdentityPoolRequest, authStateMachine: AuthStateMachine) {
self.request = request
self.authStateMachine = authStateMachine
self.taskHelper = AWSAuthTaskHelper(authStateMachine: authStateMachine)
}
public func execute() async throws -> FederateToIdentityPoolResult {
await taskHelper.didStateMachineConfigured()
let state = await authStateMachine.currentState
guard case .configured(let authNState, let authZState) = state else {
throw AuthError.invalidState(
"Federation could not be completed.",
AuthPluginErrorConstants.invalidStateError, nil)
}
if isValidAuthNStateToStart(authNState) && isValidAuthZStateToStart(authZState) {
return try await startFederatingToIdentityPool()
} else {
throw AuthError.invalidState(
"Federation could not be completed.",
AuthPluginErrorConstants.invalidStateError, nil)
}
}
func startFederatingToIdentityPool() async throws -> FederateToIdentityPoolResult {
await sendStartFederatingToIdentityPoolEvent()
let stateSequences = await authStateMachine.listen()
for await state in stateSequences {
guard case .configured(let authNState, let authZState) = state else {
continue
}
switch (authNState, authZState) {
case (.federatedToIdentityPool, .sessionEstablished(let credentials)):
return try getFederatedResult(credentials)
case (.error, .error(let authZError)):
throw authZError.authError
default:
continue
}
}
throw AuthError.unknown("Could not start federation to Identity Pool. The previous federation to identity pool credentials have been retained")
}
func sendStartFederatingToIdentityPoolEvent() async {
let federatedToken = FederatedToken(token: request.token, provider: request.provider)
let identityId = request.options.developerProvidedIdentityID
let event = AuthorizationEvent.init( eventType: .startFederationToIdentityPool(federatedToken, identityId))
await authStateMachine.send(event)
}
func isValidAuthNStateToStart(_ authNState: AuthenticationState) -> Bool {
switch authNState {
case .notConfigured, .signedOut, .federatedToIdentityPool, .error:
return true
default:
return false
}
}
func isValidAuthZStateToStart(_ authZState: AuthorizationState) -> Bool {
switch authZState {
case .configured, .sessionEstablished, .error:
return true
default:
return false
}
}
private func getFederatedResult(_ result: AmplifyCredentials)
throws -> FederateToIdentityPoolResult {
switch result {
case .identityPoolWithFederation(_, let identityId, let awsCredentials):
let federatedResult = FederateToIdentityPoolResult(
credentials: awsCredentials,
identityId: identityId)
return federatedResult
default:
throw AuthError.unknown("Unable to parse credentials to expected output", nil)
}
}
}