1 // Copyright 2022-present 650 Industries. All rights reserved. 2 3 import ABI49_0_0ExpoModulesCore 4 import AuthenticationServices 5 6 private class PresentationContextProvider: NSObject, ASWebAuthenticationPresentationContextProviding { presentationAnchornull7 func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor { 8 return UIApplication.shared.keyWindow ?? ASPresentationAnchor() 9 } 10 } 11 12 final internal class WebAuthSession { 13 var authSession: ASWebAuthenticationSession? 14 var promise: Promise? 15 var isOpen: Bool { 16 promise != nil 17 } 18 19 // It must be initialized before hand as `ASWebAuthenticationSession` holds it as a weak property 20 private var presentationContextProvider = PresentationContextProvider() 21 22 init(authUrl: URL, redirectUrl: URL?, options: AuthSessionOptions) { 23 self.authSession = ASWebAuthenticationSession( 24 url: authUrl, 25 callbackURLScheme: redirectUrl?.scheme, 26 completionHandler: { callbackUrl, error in 27 self.finish(with: [ 28 "type": callbackUrl != nil ? "success" : "cancel", 29 "url": callbackUrl?.absoluteString, 30 "error": error?.localizedDescription 31 ]) 32 } 33 ) 34 if #available(iOS 13.0, *) { 35 self.authSession?.prefersEphemeralWebBrowserSession = options.preferEphemeralSession 36 } 37 } 38 opennull39 func open(_ promise: Promise) { 40 if #available(iOS 13.0, *) { 41 authSession?.presentationContextProvider = presentationContextProvider 42 } 43 authSession?.start() 44 self.promise = promise 45 } 46 dismissnull47 func dismiss() { 48 authSession?.cancel() 49 finish(with: ["type": "dismiss"]) 50 } 51 52 // MARK: - Private 53 finishnull54 private func finish(with result: [String: String?]) { 55 promise?.resolve(result) 56 promise = nil 57 authSession = nil 58 } 59 } 60