Repository: expo/expo
File: packages/expo-web-browser/ios/WebAuthSession.swift (Swift)

Code before:
  // 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) {
    let completionHandler: ASWebAuthenticationSession.CompletionHandler = { callbackUrl, error in
      self.finish(with: [
        "type": callbackUrl != nil ? "success" : "cancel",
        "url": callbackUrl?.absoluteString,
        "error": error?.localizedDescription
      ])
    }

    // iOS 17.4+/macOS 14.4+ supports HTTPS callbacks with host/path matching
    if #available(iOS 17.4, macOS 14.4, *),
       let redirectUrl = redirectUrl,
       redirectUrl.scheme == "https",
       let host = redirectUrl.host(percentEncoded: false),
       !host.isEmpty {
      // Use the new callback API for HTTPS universal links
      // Pass empty string for path to match any path under the host if no specific path is provided
      let path = redirectUrl.path.isEmpty ? "" : redirectUrl.path
      self.authSession = ASWebAuthenticationSession(
        url: authUrl,
        callback: .https(host: host, path: path),
        completionHandler: completionHandler
      )
    } else {
      // Fallback to the old API for custom schemes or older iOS versions
      self.authSession = ASWebAuthenticationSession(
        url: authUrl,
        callbackURLScheme: redirectUrl?.scheme,
        completionHandler: completionHandler
      )
    }
    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?]) {

Review comment (security):
```suggestion
      self.authSession = ASWebAuthenticationSession(
        url: authUrl,
        callback: .https(host: host, path: redirectUrl.path),
        completionHandler: completionHandler
      )
```
`path` is not optional so it can only be empty or have value so we can leave out this check

Code after:
  // 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) {
    let completionHandler: ASWebAuthenticationSession.CompletionHandler = { callbackUrl, error in
      self.finish(with: [
        "type": callbackUrl != nil ? "success" : "cancel",
        "url": callbackUrl?.absoluteString,
        "error": error?.localizedDescription
      ])
    }

    // iOS 17.4+/macOS 14.4+ supports HTTPS callbacks with host/path matching
    if #available(iOS 17.4, macOS 14.4, *),
       let redirectUrl,
       redirectUrl.scheme == "https",
       let host = redirectUrl.host(percentEncoded: false),
       !host.isEmpty {
      // Use the new callback API for HTTPS universal links
      // Pass an empty string for the path to match any path under the host if no specific path is provided
      self.authSession = ASWebAuthenticationSession(
        url: authUrl,
        callback: .https(host: host, path: redirectUrl.path),
        completionHandler: completionHandler
      )
    } else {
      // Fallback to the old API for custom schemes or older iOS versions
      self.authSession = ASWebAuthenticationSession(
        url: authUrl,
        callbackURLScheme: redirectUrl?.scheme,
        completionHandler: completionHandler
      )
    }
    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)