Skip to content
This repository was archived by the owner on Jun 18, 2026. It is now read-only.

fix: use system browser for login instead of WKWebView - #11

Open
tdhooghe wants to merge 3 commits into
nextcloud:mainfrom
tdhooghe:fix/use-aswebauthenticationsession-for-login
Open

fix: use system browser for login instead of WKWebView#11
tdhooghe wants to merge 3 commits into
nextcloud:mainfrom
tdhooghe:fix/use-aswebauthenticationsession-for-login

Conversation

@tdhooghe

@tdhooghe tdhooghe commented Mar 8, 2026

Copy link
Copy Markdown

Summary

WKWebView silently fails cross-domain OIDC redirects when Nextcloud delegates auth to an external IdP (Authentik, Keycloak, Azure AD): the user authenticates on the IdP, but WKWebView drops the callback redirect back to the Nextcloud origin, so Login Flow v2 polls forever.

This replaces the in-app WKWebView login with the system browser via SwiftUI's webAuthenticationSession, 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): ViewModifier over @Environment(\.webAuthenticationSession). The auth Task is held in @State and cancelled when isPresented becomes false (polling success), so the sheet doesn't linger. No #if os branches, no presentation-anchor coordinator (SwiftUI supplies it on both platforms).
  • ServerAddressView.swift: .webSheet(...).loginSheet(...). userAgent is 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/v2 request.

Closes #10

Test plan

  • iOS, local credentials (no OIDC): system browser opens, polling completes, logs in
  • iOS, OIDC (e.g. Authentik): cross-domain redirect completes, polling picks up credentials
  • iOS, cancel the sheet: returns to server address screen
  • iOS, polling succeeds while sheet open: sheet auto-dismisses
  • macOS: same cases via the system browser

@tdhooghe

tdhooghe commented Mar 8, 2026

Copy link
Copy Markdown
Author

@i2h3 @mpivchev — would appreciate your review on this.

@mpivchev: this applies the same ASWebAuthenticationSession approach you implemented for the main iOS app in nextcloud/ios#3996, adapted for this shared package so all consuming apps (Notes, Deck, etc.) benefit.

@i2h3: the change is encapsulated in a single new LoginSheet view modifier — ServerAddressView stays platform-agnostic. macOS behavior is unchanged (still uses the WKWebView sheet).

@tdhooghe
tdhooghe force-pushed the fix/use-aswebauthenticationsession-for-login branch 5 times, most recently from 326ae0d to 34d8f9b Compare March 8, 2026 13:51
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>
@tdhooghe
tdhooghe force-pushed the fix/use-aswebauthenticationsession-for-login branch from 34d8f9b to acfa573 Compare March 8, 2026 13:51

@i2h3 i2h3 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@mpivchev

mpivchev commented Mar 9, 2026

Copy link
Copy Markdown
Collaborator

I need to test this with iOS Files and if possible replace the UIKit login with this. Will update soon.

@i2h3

i2h3 commented Mar 9, 2026

Copy link
Copy Markdown
Collaborator

@mpivchev You can also test it with Nextcloud Notes for iOS which uses this already.

@tdhooghe
tdhooghe force-pushed the fix/use-aswebauthenticationsession-for-login branch from ddc0764 to 41798f7 Compare March 10, 2026 09:32
Signed-off-by: Thomas Dhooghe <61279337+tdhooghe@users.noreply.github.com>
Made-with: Cursor
@tdhooghe
tdhooghe force-pushed the fix/use-aswebauthenticationsession-for-login branch from 41798f7 to a51116f Compare March 10, 2026 09:34
@tdhooghe

Copy link
Copy Markdown
Author

@i2h3 that was indeed the app that caused me to raise this PR 🙂

Comment on lines +28 to +31
#if os(iOS)
@State private var authSession: ASWebAuthenticationSession?
@State private var sessionCoordinator = SessionCoordinator()
#endif

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why iOS only? I recently used @Environment(\.webAuthenticationSession) private var webAuthenticationSession in a toy project for macOS and it works fine there, too.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@tdhooghe tdhooghe changed the title fix(iOS): use ASWebAuthenticationSession instead of WKWebView for login fix: use system browser for login instead of WKWebView Jun 18, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Login flow fails with OIDC providers due to WKWebView cross-domain redirect limitation

3 participants