amplify-swift/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Actions/SignOut/ShowHostedUISignOut.swift

119 lines
4.7 KiB
Swift

//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
import Amplify
import Foundation
import AuthenticationServices
class ShowHostedUISignOut: NSObject, Action {
var identifier: String = "ShowHostedUISignOut"
let signOutEvent: SignOutEventData
let signInData: SignedInData
var sessionAdapter: HostedUISessionBehavior?
init(signOutEvent: SignOutEventData, signInData: SignedInData) {
self.signInData = signInData
self.signOutEvent = signOutEvent
}
func execute(withDispatcher dispatcher: EventDispatcher, environment: Environment) async {
logVerbose("\(#fileID) Starting execution", environment: environment)
guard let environment = environment as? AuthEnvironment,
let hostedUIEnvironment = environment.hostedUIEnvironment else {
let message = AuthPluginErrorConstants.configurationError
let error = AuthenticationError.configuration(message: message)
await sendEvent(with: error, dispatcher: dispatcher, environment: environment)
return
}
let hostedUIConfig = hostedUIEnvironment.configuration
guard let callbackURL = URL(string: hostedUIConfig.oauth.signOutRedirectURI),
let callbackURLScheme = callbackURL.scheme else {
let error = AuthenticationError.configuration(message: "Callback URL could not be retrieved")
await sendEvent(with: error, dispatcher: dispatcher, environment: environment)
return
}
do {
let logoutURL = try HostedUIRequestHelper.createSignOutURL(configuration: hostedUIConfig)
_ = try await withCheckedThrowingContinuation {
(continuation: CheckedContinuation<[URLQueryItem], Error>) in
sessionAdapter = hostedUIEnvironment.hostedUISessionFactory()
sessionAdapter?.showHostedUI(url: logoutURL,
callbackScheme: callbackURLScheme,
inPrivate: false,
presentationAnchor: signOutEvent.presentationAnchor) {
result in
continuation.resume(with: result)
}
}
await sendEvent(with: nil, dispatcher: dispatcher, environment: environment)
} catch HostedUIError.signOutURI {
let error = AuthenticationError.configuration(message: "Could not create logout URL")
await sendEvent(with: error, dispatcher: dispatcher, environment: environment)
return
} catch {
self.logVerbose("\(#fileID) Received error \(error)", environment: environment)
await sendEvent(with: error, dispatcher: dispatcher, environment: environment)
}
}
func sendEvent(with error: Error?,
dispatcher: EventDispatcher,
environment: Environment) async {
var hostedUIError: AWSCognitoHostedUIError?
if let hostedUIInternalError = error as? HostedUIError,
case .cancelled = hostedUIInternalError {
let event = SignOutEvent(eventType: .userCancelled)
self.logVerbose("\(#fileID) Sending event \(event.type)", environment: environment)
await dispatcher.send(event)
return
}
if let error = error as? AuthErrorConvertible {
hostedUIError = AWSCognitoHostedUIError(error: error.authError)
} else if let error = error {
let serviceError = AuthError.service("HostedUI failed with error",
"", error)
hostedUIError = AWSCognitoHostedUIError(error: serviceError)
}
let event: SignOutEvent
if self.signOutEvent.globalSignOut {
event = SignOutEvent(eventType: .signOutGlobally(self.signInData,
hostedUIError: hostedUIError))
} else {
event = SignOutEvent(eventType: .revokeToken(self.signInData,
hostedUIError: hostedUIError))
}
self.logVerbose("\(#fileID) Sending event \(event.type)", environment: environment)
await dispatcher.send(event)
}
}
extension ShowHostedUISignOut: CustomDebugDictionaryConvertible {
var debugDictionary: [String: Any] {
[
"identifier": identifier,
"signInData": signInData.debugDictionary,
"signOutEvent": signOutEvent.debugDictionary
]
}
}
extension ShowHostedUISignOut {
override var debugDescription: String {
debugDictionary.debugDescription
}
}