Refactor auth to ASWebAuthenticationSession

This commit is contained in:
Thomas Ricouard 2023-12-06 08:05:26 +01:00
parent a6f6aa3a02
commit 3d2171d716
3 changed files with 28 additions and 24 deletions

View File

@ -3,6 +3,7 @@ import Env
import Observation import Observation
import SafariServices import SafariServices
import SwiftUI import SwiftUI
import Models
extension View { extension View {
@MainActor func withSafariRouter() -> some View { @MainActor func withSafariRouter() -> some View {
@ -26,7 +27,7 @@ private struct SafariRouter: ViewModifier {
}) })
.onOpenURL { url in .onOpenURL { url in
// Open external URL (from icecubesapp://) // Open external URL (from icecubesapp://)
let urlString = url.absoluteString.replacingOccurrences(of: "icecubesapp://", with: "https://") let urlString = url.absoluteString.replacingOccurrences(of: AppInfo.scheme, with: "https://")
guard let url = URL(string: urlString), url.host != nil else { return } guard let url = URL(string: urlString), url.host != nil else { return }
_ = routerPath.handle(url: url) _ = routerPath.handle(url: url)
} }

View File

@ -1,4 +1,5 @@
import AppAccount import AppAccount
import AuthenticationServices
import Combine import Combine
import DesignSystem import DesignSystem
import Env import Env
@ -27,7 +28,6 @@ struct AddAccountView: View {
@State private var signInClient: Client? @State private var signInClient: Client?
@State private var instances: [InstanceSocial] = [] @State private var instances: [InstanceSocial] = []
@State private var instanceFetchError: LocalizedStringKey? @State private var instanceFetchError: LocalizedStringKey?
@State private var oauthURL: URL?
private let instanceNamePublisher = PassthroughSubject<String, Never>() private let instanceNamePublisher = PassthroughSubject<String, Never>()
@ -136,21 +136,6 @@ struct AddAccountView: View {
break break
} }
} }
.onOpenURL(perform: { url in
Task {
await continueSignIn(url: url)
}
})
.onChange(of: oauthURL) { _, newValue in
if newValue == nil {
isSigninIn = false
}
}
#if !targetEnvironment(macCatalyst)
.sheet(item: $oauthURL, content: { url in
SafariView(url: url)
})
#endif
} }
} }
@ -233,11 +218,19 @@ struct AddAccountView: View {
do { do {
signInClient = .init(server: sanitizedName) signInClient = .init(server: sanitizedName)
if let oauthURL = try await signInClient?.oauthURL() { if let oauthURL = try await signInClient?.oauthURL() {
#if targetEnvironment(macCatalyst) let session = ASWebAuthenticationSession(url: oauthURL,
openURL(oauthURL) callbackURLScheme: AppInfo.scheme.replacingOccurrences(of: "://", with: ""))
#else { callbackURL, error in
self.oauthURL = oauthURL if let callbackURL {
#endif Task {
await continueSignIn(url: callbackURL)
}
} else {
isSigninIn = false
}
}
session.presentationContextProvider = SceneDelegate.authViewController
session.start()
} else { } else {
isSigninIn = false isSigninIn = false
} }
@ -252,7 +245,6 @@ struct AddAccountView: View {
return return
} }
do { do {
oauthURL = nil
let oauthToken = try await client.continueOauthFlow(url: url) let oauthToken = try await client.continueOauthFlow(url: url)
let client = Client(server: client.server, oauthToken: oauthToken) let client = Client(server: client.server, oauthToken: oauthToken)
let account: Account = try await client.get(endpoint: Accounts.verifyCredentials) let account: Account = try await client.get(endpoint: Accounts.verifyCredentials)
@ -266,7 +258,6 @@ struct AddAccountView: View {
isSigninIn = false isSigninIn = false
dismiss() dismiss()
} catch { } catch {
oauthURL = nil
isSigninIn = false isSigninIn = false
} }
} }

View File

@ -1,4 +1,5 @@
import Combine import Combine
import AuthenticationServices
import UIKit import UIKit
@Observable @Observable
@ -6,6 +7,9 @@ public class SceneDelegate: NSObject, UIWindowSceneDelegate, Sendable {
public var window: UIWindow? public var window: UIWindow?
public private(set) var windowWidth: CGFloat = UIScreen.main.bounds.size.width public private(set) var windowWidth: CGFloat = UIScreen.main.bounds.size.width
public private(set) var windowHeight: CGFloat = UIScreen.main.bounds.size.height public private(set) var windowHeight: CGFloat = UIScreen.main.bounds.size.height
public static var globalPresentationAnchor: ASPresentationAnchor? = nil
public static var authViewController = AuthViewController()
public func scene(_ scene: UIScene, public func scene(_ scene: UIScene,
willConnectTo _: UISceneSession, willConnectTo _: UISceneSession,
@ -13,6 +17,8 @@ public class SceneDelegate: NSObject, UIWindowSceneDelegate, Sendable {
{ {
guard let windowScene = scene as? UIWindowScene else { return } guard let windowScene = scene as? UIWindowScene else { return }
window = windowScene.keyWindow window = windowScene.keyWindow
Self.globalPresentationAnchor = window
#if targetEnvironment(macCatalyst) #if targetEnvironment(macCatalyst)
if let titlebar = windowScene.titlebar { if let titlebar = windowScene.titlebar {
@ -54,3 +60,9 @@ public class SceneDelegate: NSObject, UIWindowSceneDelegate, Sendable {
} }
} }
} }
public class AuthViewController: UIViewController, ASWebAuthenticationPresentationContextProviding {
public func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
return SceneDelegate.globalPresentationAnchor ?? ASPresentationAnchor()
}
}