60 lines
1.7 KiB
Swift
60 lines
1.7 KiB
Swift
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
|
|
import ExpoModulesCore
|
|
import AuthenticationServices
|
|
|
|
private class PresentationContextProvider: NSObject, ASWebAuthenticationPresentationContextProviding {
|
|
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
|
|
#if os(iOS)
|
|
return UIApplication.shared.keyWindow ?? ASPresentationAnchor()
|
|
#else
|
|
return NSApp.mainWindow ?? ASPresentationAnchor()
|
|
#endif
|
|
}
|
|
}
|
|
|
|
final internal class WebAuthSession {
|
|
var authSession: ASWebAuthenticationSession?
|
|
var promise: Promise?
|
|
var isOpen: Bool {
|
|
promise != nil
|
|
}
|
|
|
|
// It must be initialized before hand as `ASWebAuthenticationSession` holds it as a weak property
|
|
private var presentationContextProvider = PresentationContextProvider()
|
|
|
|
init(authUrl: URL, redirectUrl: URL?, options: AuthSessionOptions) {
|
|
self.authSession = ASWebAuthenticationSession(
|
|
url: authUrl,
|
|
callbackURLScheme: redirectUrl?.scheme,
|
|
completionHandler: { callbackUrl, error in
|
|
self.finish(with: [
|
|
"type": callbackUrl != nil ? "success" : "cancel",
|
|
"url": callbackUrl?.absoluteString,
|
|
"error": error?.localizedDescription
|
|
])
|
|
}
|
|
)
|
|
self.authSession?.prefersEphemeralWebBrowserSession = options.preferEphemeralSession
|
|
}
|
|
|
|
func open(_ promise: Promise) {
|
|
authSession?.presentationContextProvider = presentationContextProvider
|
|
authSession?.start()
|
|
self.promise = promise
|
|
}
|
|
|
|
func dismiss() {
|
|
authSession?.cancel()
|
|
finish(with: ["type": "dismiss"])
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
private func finish(with result: [String: String?]) {
|
|
promise?.resolve(result)
|
|
promise = nil
|
|
authSession = nil
|
|
}
|
|
}
|