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