Skip to content

Commit

Permalink
Merge pull request #1013 from ItzNotABug/feat-signin
Browse files Browse the repository at this point in the history
Feat: In-App OAuth2 Sign-in
  • Loading branch information
abnegate authored Dec 12, 2024
2 parents a852aba + c8a11fb commit 39768de
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 14 deletions.
11 changes: 7 additions & 4 deletions templates/apple/base/requests/oauth.twig
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
let callbackScheme = "appwrite-callback-\(client.config["project"] ?? "")"

_ = try await withCheckedThrowingContinuation { continuation in
WebAuthComponent.authenticate(url: url, callbackScheme: callbackScheme) { result in
continuation.resume(with: result)
/// main thread for PresentationContextProvider
DispatchQueue.main.async {
WebAuthComponent.authenticate(url: url, callbackScheme: callbackScheme) { result in
continuation.resume(with: result)
}
}
}
return true

return true
57 changes: 47 additions & 10 deletions templates/swift/Sources/OAuth/WebAuthComponent.swift.twig
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import AsyncHTTPClient
import Foundation
import NIO

#if canImport(SwiftUI)
import SwiftUI
#if canImport(AuthenticationServices)
import AuthenticationServices
#endif

///
Expand All @@ -13,12 +13,10 @@ import SwiftUI
@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, visionOS 1.0, *)
public class WebAuthComponent {

#if canImport(SwiftUI)
@Environment(\.openURL)
private static var openURL
#endif

private static var callbacks = [String: (Result<String, {{ spec.title | caseUcfirst}}Error>) -> Void]()
#if canImport(AuthenticationServices)
private static var currentAuthSession: ASWebAuthenticationSession?
#endif

///
/// Authenticate Session with OAuth2
Expand All @@ -41,9 +39,29 @@ public class WebAuthComponent {
) {
callbacks[callbackScheme] = onComplete

#if canImport(SwiftUI)
openURL(url)
#endif
#if canImport(AuthenticationServices)
currentAuthSession = ASWebAuthenticationSession(
url: url,
callbackURLScheme: callbackScheme
) { callbackURL, error in
if let error = error {
cleanUp()
} else if let callbackURL = callbackURL {
// handle cookies here itself!
WebAuthComponent.handleIncomingCookie(from: callbackURL)
cleanUp()
}
}

if let session = currentAuthSession {
/// Indicates that the session should be a private session.
session.prefersEphemeralWebBrowserSession = true
session.presentationContextProvider = PresentationContextProvider.shared
session.start()
} else {
print("Failed to create ASWebAuthenticationSession")
}
#endif
}

///
Expand Down Expand Up @@ -130,5 +148,24 @@ public class WebAuthComponent {
callbacks.forEach { (_, callback) in
callback(.failure({{ spec.title | caseUcfirst}}Error(message: "User cancelled login.")))
}

#if canImport(AuthenticationServices)
currentAuthSession = nil
#endif
}
}

#if canImport(AuthenticationServices)
/// Presentation context for the ASWebAuthenticationSession.
class PresentationContextProvider: NSObject, ASWebAuthenticationPresentationContextProviding {
static let shared = PresentationContextProvider()

func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
if let mainWindow = OSApplication.shared.windows.first { $0.isKeyWindow } {
return mainWindow
}

return ASPresentationAnchor()
}
}
#endif

0 comments on commit 39768de

Please sign in to comment.