248 lines
11 KiB
Swift
248 lines
11 KiB
Swift
//
|
|
// Copyright Amazon.com Inc. or its affiliates.
|
|
// All Rights Reserved.
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
import Foundation
|
|
import Amplify
|
|
|
|
import AWSCognitoIdentity
|
|
import AWSCognitoIdentityProvider
|
|
import AWSPluginsCore
|
|
|
|
import ClientRuntime
|
|
|
|
extension AWSCognitoAuthPlugin {
|
|
|
|
/// Configures AWSCognitoAuthPlugin with the specified configuration.
|
|
///
|
|
/// - Parameter configuration: The configuration specified for this plugin
|
|
/// - Throws:
|
|
/// - PluginError.pluginConfigurationError: If one of the configuration values is invalid or empty
|
|
public func configure(using configuration: Any?) throws {
|
|
|
|
guard let jsonValueConfiguration = configuration as? JSONValue else {
|
|
throw PluginError.pluginConfigurationError(
|
|
AuthPluginErrorConstants.decodeConfigurationError.errorDescription,
|
|
AuthPluginErrorConstants.decodeConfigurationError.recoverySuggestion)
|
|
}
|
|
|
|
let authConfiguration = try ConfigurationHelper.authConfiguration(jsonValueConfiguration)
|
|
|
|
let credentialStoreResolver = CredentialStoreState.Resolver().eraseToAnyResolver()
|
|
let credentialEnvironment = credentialStoreEnvironment(authConfiguration: authConfiguration)
|
|
let credentialStoreMachine = StateMachine(resolver: credentialStoreResolver,
|
|
environment: credentialEnvironment)
|
|
let credentialsClient = CredentialStoreOperationClient(
|
|
credentialStoreStateMachine: credentialStoreMachine)
|
|
|
|
let authResolver = AuthState.Resolver().eraseToAnyResolver()
|
|
let authEnvironment = makeAuthEnvironment(
|
|
authConfiguration: authConfiguration,
|
|
credentialsClient: credentialsClient
|
|
)
|
|
|
|
let authStateMachine = StateMachine(resolver: authResolver, environment: authEnvironment)
|
|
|
|
let hubEventHandler = AuthHubEventHandler()
|
|
let analyticsHandler = try UserPoolAnalytics(
|
|
authConfiguration.getUserPoolConfiguration(),
|
|
credentialStoreEnvironment: credentialEnvironment.credentialStoreEnvironment)
|
|
|
|
configure(authConfiguration: authConfiguration,
|
|
authEnvironment: authEnvironment,
|
|
authStateMachine: authStateMachine,
|
|
credentialStoreStateMachine: credentialStoreMachine,
|
|
hubEventHandler: hubEventHandler,
|
|
analyticsHandler: analyticsHandler)
|
|
}
|
|
|
|
func configure(authConfiguration: AuthConfiguration,
|
|
authEnvironment: AuthEnvironment,
|
|
authStateMachine: AuthStateMachine,
|
|
credentialStoreStateMachine: CredentialStoreStateMachine,
|
|
hubEventHandler: AuthHubEventBehavior,
|
|
analyticsHandler: UserPoolAnalyticsBehavior,
|
|
queue: OperationQueue = OperationQueue()) {
|
|
|
|
self.authConfiguration = authConfiguration
|
|
self.queue = queue
|
|
self.queue.maxConcurrentOperationCount = 1
|
|
self.authEnvironment = authEnvironment
|
|
self.authStateMachine = authStateMachine
|
|
self.credentialStoreStateMachine = credentialStoreStateMachine
|
|
self.internalConfigure()
|
|
self.listenToStateMachineChanges()
|
|
self.hubEventHandler = hubEventHandler
|
|
self.analyticsHandler = analyticsHandler
|
|
self.taskQueue = TaskQueue()
|
|
}
|
|
|
|
// MARK: - Configure Helpers
|
|
private func makeUserPool() throws -> CognitoUserPoolBehavior {
|
|
switch authConfiguration {
|
|
case .userPools(let userPoolConfig), .userPoolsAndIdentityPools(let userPoolConfig, _):
|
|
|
|
let configuration: CognitoIdentityProviderClient.CognitoIdentityProviderClientConfiguration
|
|
if let customEndpoint = userPoolConfig.endpoint {
|
|
configuration = try .init(
|
|
region: userPoolConfig.region,
|
|
endpointResolver: customEndpoint.resolver,
|
|
frameworkMetadata: AmplifyAWSServiceConfiguration.frameworkMetaData()
|
|
)
|
|
} else {
|
|
configuration = try CognitoIdentityProviderClient.CognitoIdentityProviderClientConfiguration(
|
|
region: userPoolConfig.region, frameworkMetadata: AmplifyAWSServiceConfiguration.frameworkMetaData())
|
|
}
|
|
|
|
return CognitoIdentityProviderClient(config: configuration)
|
|
|
|
default:
|
|
fatalError()
|
|
}
|
|
}
|
|
|
|
private func makeIdentityClient() throws -> CognitoIdentityBehavior {
|
|
switch authConfiguration {
|
|
case .identityPools(let identityPoolConfig), .userPoolsAndIdentityPools(_, let identityPoolConfig):
|
|
let configuration = try CognitoIdentityClient.CognitoIdentityClientConfiguration(
|
|
region: identityPoolConfig.region, frameworkMetadata: AmplifyAWSServiceConfiguration.frameworkMetaData())
|
|
return CognitoIdentityClient(config: configuration)
|
|
default:
|
|
fatalError()
|
|
}
|
|
}
|
|
|
|
private func makeHostedUISession() -> HostedUISessionBehavior {
|
|
return HostedUIASWebAuthenticationSession()
|
|
}
|
|
|
|
private func makeURLSession() -> URLSession {
|
|
return URLSession.shared
|
|
}
|
|
|
|
private func makeRandomString() -> RandomStringBehavior {
|
|
return RandomStringGenerator()
|
|
}
|
|
|
|
private func makeCognitoASF() -> AdvancedSecurityBehavior {
|
|
CognitoUserPoolASF()
|
|
}
|
|
|
|
private func makeUserPoolAnalytics() -> UserPoolAnalyticsBehavior {
|
|
return analyticsHandler
|
|
}
|
|
|
|
private func makeCredentialStore() -> AmplifyAuthCredentialStoreBehavior {
|
|
AWSCognitoAuthCredentialStore(authConfiguration: authConfiguration)
|
|
}
|
|
|
|
private func makeLegacyKeychainStore(service: String) -> KeychainStoreBehavior {
|
|
KeychainStore(service: service)
|
|
}
|
|
|
|
private func makeAuthEnvironment(
|
|
authConfiguration: AuthConfiguration,
|
|
credentialsClient: CredentialStoreStateBehavior
|
|
) -> AuthEnvironment {
|
|
|
|
switch authConfiguration {
|
|
case .userPools(let userPoolConfigurationData):
|
|
let authenticationEnvironment = authenticationEnvironment(
|
|
userPoolConfigData: userPoolConfigurationData)
|
|
|
|
return AuthEnvironment(
|
|
configuration: authConfiguration,
|
|
userPoolConfigData: userPoolConfigurationData,
|
|
identityPoolConfigData: nil,
|
|
authenticationEnvironment: authenticationEnvironment,
|
|
authorizationEnvironment: nil,
|
|
credentialsClient: credentialsClient,
|
|
logger: log)
|
|
|
|
case .identityPools(let identityPoolConfigurationData):
|
|
let authorizationEnvironment = authorizationEnvironment(
|
|
identityPoolConfigData: identityPoolConfigurationData)
|
|
return AuthEnvironment(
|
|
configuration: authConfiguration,
|
|
userPoolConfigData: nil,
|
|
identityPoolConfigData: identityPoolConfigurationData,
|
|
authenticationEnvironment: nil,
|
|
authorizationEnvironment: authorizationEnvironment,
|
|
credentialsClient: credentialsClient,
|
|
logger: log)
|
|
|
|
case .userPoolsAndIdentityPools(let userPoolConfigurationData,
|
|
let identityPoolConfigurationData):
|
|
let authenticationEnvironment = authenticationEnvironment(
|
|
userPoolConfigData: userPoolConfigurationData)
|
|
let authorizationEnvironment = authorizationEnvironment(
|
|
identityPoolConfigData: identityPoolConfigurationData)
|
|
return AuthEnvironment(
|
|
configuration: authConfiguration,
|
|
userPoolConfigData: userPoolConfigurationData,
|
|
identityPoolConfigData: identityPoolConfigurationData,
|
|
authenticationEnvironment: authenticationEnvironment,
|
|
authorizationEnvironment: authorizationEnvironment,
|
|
credentialsClient: credentialsClient,
|
|
logger: log)
|
|
}
|
|
}
|
|
|
|
private func authenticationEnvironment(userPoolConfigData: UserPoolConfigurationData) -> AuthenticationEnvironment {
|
|
|
|
let srpAuthEnvironment = BasicSRPAuthEnvironment(userPoolConfiguration: userPoolConfigData,
|
|
cognitoUserPoolFactory: makeUserPool)
|
|
let srpSignInEnvironment = BasicSRPSignInEnvironment(srpAuthEnvironment: srpAuthEnvironment)
|
|
let userPoolEnvironment = BasicUserPoolEnvironment(
|
|
userPoolConfiguration: userPoolConfigData,
|
|
cognitoUserPoolFactory: makeUserPool,
|
|
cognitoUserPoolASFFactory: makeCognitoASF,
|
|
cognitoUserPoolAnalyticsHandlerFactory: makeUserPoolAnalytics)
|
|
let hostedUIEnvironment = hostedUIEnvironment(userPoolConfigData)
|
|
return BasicAuthenticationEnvironment(srpSignInEnvironment: srpSignInEnvironment,
|
|
userPoolEnvironment: userPoolEnvironment,
|
|
hostedUIEnvironment: hostedUIEnvironment)
|
|
}
|
|
|
|
private func hostedUIEnvironment(_ configuration: UserPoolConfigurationData) -> HostedUIEnvironment? {
|
|
guard let hostedUIConfig = configuration.hostedUIConfig else {
|
|
return nil
|
|
}
|
|
return BasicHostedUIEnvironment(configuration: hostedUIConfig,
|
|
hostedUISessionFactory: makeHostedUISession,
|
|
urlSessionFactory: makeURLSession,
|
|
randomStringFactory: makeRandomString)
|
|
}
|
|
|
|
private func authorizationEnvironment(identityPoolConfigData: IdentityPoolConfigurationData) -> AuthorizationEnvironment {
|
|
BasicAuthorizationEnvironment(identityPoolConfiguration: identityPoolConfigData,
|
|
cognitoIdentityFactory: makeIdentityClient)
|
|
}
|
|
|
|
private func credentialStoreEnvironment(authConfiguration: AuthConfiguration) -> CredentialEnvironment {
|
|
CredentialEnvironment(
|
|
authConfiguration: authConfiguration,
|
|
credentialStoreEnvironment: BasicCredentialStoreEnvironment(
|
|
amplifyCredentialStoreFactory: makeCredentialStore,
|
|
legacyKeychainStoreFactory: makeLegacyKeychainStore(service:)
|
|
), logger: log
|
|
)
|
|
}
|
|
|
|
private func internalConfigure() {
|
|
let request = AuthConfigureRequest(authConfiguration: authConfiguration)
|
|
let operation = AuthConfigureOperation(
|
|
request: request,
|
|
authStateMachine: authStateMachine,
|
|
credentialStoreStateMachine: credentialStoreStateMachine)
|
|
self.queue.addOperation(operation)
|
|
}
|
|
}
|
|
|
|
extension CognitoIdentityProviderClient: CognitoUserPoolBehavior {}
|
|
|
|
extension CognitoIdentityClient: CognitoIdentityBehavior {}
|