fix: use system browser for login instead of WKWebView - #11
Conversation
dce83ee to
d89a88f
Compare
|
@i2h3 @mpivchev — would appreciate your review on this. @mpivchev: this applies the same @i2h3: the change is encapsulated in a single new |
326ae0d to
34d8f9b
Compare
WKWebView silently fails to complete cross-domain OIDC redirects (e.g. when Nextcloud delegates authentication to an external IdP like Authentik). The user authenticates successfully on the IdP side, but WKWebView drops the callback redirect back to the Nextcloud origin, leaving the login flow stuck in a polling loop that never resolves. Replace WKWebView with ASWebAuthenticationSession on iOS via a new LoginSheet view modifier that encapsulates the platform difference: - iOS: ASWebAuthenticationSession (system browser, handles OIDC/passkeys) - macOS: WKWebView sheet (unchanged behavior) ServerAddressView is now platform-agnostic — it just sets isPresented and the modifier does the right thing per platform. Credentials continue to be obtained via the host app's existing polling mechanism. Ref: nextcloud/ios#3996 (same fix applied to the main iOS app) Signed-off-by: Thomas Dhooghe <61279337+tdhooghe@users.noreply.github.com>
34d8f9b to
acfa573
Compare
i2h3
left a comment
There was a problem hiding this comment.
Looks fine to me, though I have only reviewed the code changes and did not test it in context of the iOS apps. Please verify, @mpivchev and @marinofaggiana.
|
I need to test this with iOS Files and if possible replace the UIKit login with this. Will update soon. |
|
@mpivchev You can also test it with Nextcloud Notes for iOS which uses this already. |
ddc0764 to
41798f7
Compare
Signed-off-by: Thomas Dhooghe <61279337+tdhooghe@users.noreply.github.com> Made-with: Cursor
41798f7 to
a51116f
Compare
|
@i2h3 that was indeed the app that caused me to raise this PR 🙂 |
| #if os(iOS) | ||
| @State private var authSession: ASWebAuthenticationSession? | ||
| @State private var sessionCoordinator = SessionCoordinator() | ||
| #endif |
There was a problem hiding this comment.
Why iOS only? I recently used @Environment(\.webAuthenticationSession) private var webAuthenticationSession in a toy project for macOS and it works fine there, too.
There was a problem hiding this comment.
yeah good call. i'll move both platforms to webAuthenticationSession and drop the #if os split + the SessionCoordinator.
macOS is still on WKWebView today so it's probably hitting the same OIDC redirect issue, though i haven't tested that yet.
one thing to decide: this kills userAgent, since the system browser won't let you set a custom UA. doesn't affect the app password name though (that comes from the host app's /login/v2 call, not the webview), and notes-ios is the only consumer i can find so dropping it is a one liner there. drop it or keep for API stability?
Replace the per-platform split (ASWebAuthenticationSession on iOS, WKWebView sheet on macOS) with SwiftUI's webAuthenticationSession, which provides the presentation anchor on both platforms. Drops the SessionCoordinator and the #if os branches. macOS now goes through the system browser instead of WKWebView, so the same OIDC redirect handling applies there too. Login Flow v2 has no callback to complete, so the session is cancelled once polling reports success (isPresented becomes false). Stop forwarding userAgent to the login UI since the system browser can't set a custom UA. The app password name is unaffected, it comes from the host app's /login/v2 request. Signed-off-by: Thomas Dhooghe <61279337+tdhooghe@users.noreply.github.com>
Summary
WKWebViewsilently fails cross-domain OIDC redirects when Nextcloud delegates auth to an external IdP (Authentik, Keycloak, Azure AD): the user authenticates on the IdP, butWKWebViewdrops the callback redirect back to the Nextcloud origin, so Login Flow v2 polls forever.This replaces the in-app
WKWebViewlogin with the system browser via SwiftUI'swebAuthenticationSession, on both iOS and macOS. The system browser handles cross-domain OIDC redirects, passkeys/WebAuthn, and deep links. Credentials are still obtained via the host app's polling; no change to the polling API.Same approach as the main iOS app (nextcloud/ios#3996), here in the shared package so consuming apps inherit it.
Changes
LoginSheet.swift(new):ViewModifierover@Environment(\.webAuthenticationSession). The authTaskis held in@Stateand cancelled whenisPresentedbecomesfalse(polling success), so the sheet doesn't linger. No#if osbranches, no presentation-anchor coordinator (SwiftUI supplies it on both platforms).ServerAddressView.swift:.webSheet(...)→.loginSheet(...).userAgentis no longer forwarded (the system browser can't set a custom UA); the public param is kept, and the app password name is unaffected since it comes from the host app's/login/v2request.Closes #10
Test plan