(auth): Add proxy authentication WebView for server login
This commit is contained in:
@@ -20,3 +20,4 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,3 +6,4 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -16,3 +16,4 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M240-40q-50 0-85-35t-35-85q0-50 35-85t85-35q14 0 26 3t23 8l57-71q-28-31-39-70t-5-78l-81-27q-17 25-43 40t-58 15q-50 0-85-35T0-580q0-50 35-85t85-35q50 0 85 35t35 85v8l81 28q20-36 53.5-61t75.5-32v-87q-39-11-64.5-42.5T360-840q0-50 35-85t85-35q50 0 85 35t35 85q0 42-26 73.5T510-724v87q42 7 75.5 32t53.5 61l81-28v-8q0-50 35-85t85-35q50 0 85 35t35 85q0 50-35 85t-85 35q-32 0-58.5-15T739-515l-81 27q6 39-5 77.5T614-340l57 70q11-5 23-7.5t26-2.5q50 0 85 35t35 85q0 50-35 85t-85 35q-50 0-85-35t-35-85q0-20 6.5-38.5T624-232l-57-71q-41 23-87.5 23T392-303l-56 71q11 15 17.5 33.5T360-160q0 50-35 85t-85 35Z" fill="currentColor"/></svg>
|
||||
|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 720 B After Width: | Height: | Size: 721 B |
@@ -38,3 +38,4 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,3 +10,4 @@
|
||||
</plist>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -11,3 +11,4 @@
|
||||
</plist>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import Flutter
|
||||
import AppIntents
|
||||
import UIKit
|
||||
import UniformTypeIdentifiers
|
||||
import WebKit
|
||||
|
||||
final class VoiceBackgroundAudioManager {
|
||||
static let shared = VoiceBackgroundAudioManager()
|
||||
@@ -613,6 +614,18 @@ struct AppShortcuts: AppShortcutsProvider {
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
private var backgroundStreamingHandler: BackgroundStreamingHandler?
|
||||
|
||||
/// Checks if a cookie matches a given URL based on domain.
|
||||
private func cookieMatchesUrl(cookie: HTTPCookie, url: URL) -> Bool {
|
||||
guard let host = url.host?.lowercased() else { return false }
|
||||
let domain = cookie.domain.lowercased()
|
||||
|
||||
// Remove leading dot from cookie domain if present
|
||||
let cleanDomain = domain.hasPrefix(".") ? String(domain.dropFirst()) : domain
|
||||
|
||||
// Exact match or subdomain match
|
||||
return host == cleanDomain || host.hasSuffix(".\(cleanDomain)")
|
||||
}
|
||||
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
@@ -645,6 +658,46 @@ struct AppShortcuts: AppShortcutsProvider {
|
||||
}
|
||||
}
|
||||
|
||||
// Setup cookie manager channel for WebView cookie access
|
||||
if let registrar = self.registrar(forPlugin: "CookieManagerChannel") {
|
||||
let cookieChannel = FlutterMethodChannel(
|
||||
name: "com.conduit.app/cookies",
|
||||
binaryMessenger: registrar.messenger()
|
||||
)
|
||||
|
||||
cookieChannel.setMethodCallHandler { [weak self] (call, result) in
|
||||
if call.method == "getCookies" {
|
||||
guard let args = call.arguments as? [String: Any],
|
||||
let urlString = args["url"] as? String,
|
||||
let url = URL(string: urlString) else {
|
||||
result(FlutterError(code: "INVALID_ARGS", message: "Invalid URL", details: nil))
|
||||
return
|
||||
}
|
||||
|
||||
// Get cookies from WKWebView's cookie store
|
||||
WKWebsiteDataStore.default().httpCookieStore.getAllCookies { [weak self] cookies in
|
||||
guard let self = self else {
|
||||
// Always call result to avoid leaving Dart side hanging
|
||||
result([:])
|
||||
return
|
||||
}
|
||||
var cookieDict: [String: String] = [:]
|
||||
|
||||
for cookie in cookies {
|
||||
// Filter cookies for this domain
|
||||
if self.cookieMatchesUrl(cookie: cookie, url: url) {
|
||||
cookieDict[cookie.name] = cookie.value
|
||||
}
|
||||
}
|
||||
|
||||
result(cookieDict)
|
||||
}
|
||||
} else {
|
||||
result(FlutterMethodNotImplemented)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
CFBundleDisplayName = "Conduit";
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
CFBundleDisplayName = "Conduit";
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
CFBundleDisplayName = "Conduit";
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
CFBundleDisplayName = "Conduit";
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
CFBundleDisplayName = "Conduit";
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
CFBundleDisplayName = "Conduit";
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
CFBundleDisplayName = "Conduit";
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
CFBundleDisplayName = "Conduit";
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
CFBundleDisplayName = "Conduit";
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
CFBundleDisplayName = "Conduit";
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user