Transition to Claimed HTTPS URIs

Hi again everyone. I will be providing an updated and optimized solution regarding the current topic.

You are using Auth0.OidcClient.MAUI v1.4.0 for a .NET MAUI cross-platform mobile app. Login and logout work as expected on Android with the https:// scheme, but on iOS you are experiencing two critical issues:

  1. Logout hangs on the callback site: After initiating logout, the browser window never closes; instead, it remains open on the callback page.
  2. Login sometimes fails: After pressing "Continue" on the Universal Login page, the page remains on the login screen instead of redirecting back to the app.

The Dashboard shows all operations as "successful," and your app correctly opens when you manually tap the callback link from notes, suggesting universal links are properly configured. You are testing on iOS 18.7.7 and iPadOS 16.4.

This is a platform-specific callback routing issue on iOS caused by cookie-sharing behavior in the browser session. The solution requires proper HTTPS universal link configuration with associated domains, combined with ephemeral session handling to prevent shared cookies from interfering with callback dismissal.

[Root Cause]

iOS uses ASWebAuthenticationSession to handle OAuth callbacks. By default, this API stores session cookies in the shared Safari cookie jar to enable Single Sign-On (SSO). However, this shared session can cause two problems:

  1. Logout hangs: When logging out, the shared cookie persists, and the browser does not receive a clear dismissal signal. The logout callback is processed, but the browser window remains open because the session is still active.
  2. Login remains on Universal Login page: If a previous session cookie exists, the browser may not properly route the callback back to your app, or the callback is processed but the browser modal does not dismiss because the session state is ambiguous.

Additionally, if your associated domain configuration is incomplete or the AASA file is not properly cached, the universal link may not be recognized during the automated OAuth flow, even though manual tapping works (manual tapping uses a different code path).

[Solution]

Step 1: Verify and configure associated domains in your MAUI iOS project

Open Platforms/iOS/Info.plist and add the associated domain entry:

<key>com.apple.developer.associated-domains</key>
<array>
    <string>webcredentials:yourcompany.com</string>
</array>

Replace yourcompany.com with your actual callback domain (the domain part of your callback URL, e.g., https://yourcompany.com/callbackyourcompany.com).

Step 2: Verify the AASA file is properly hosted

Auth0 automatically generates the apple-app-site-association (AASA) file at https://your-auth0-domain/.well-known/apple-app-site-association.

Verify that the file is accessible and contains your app's Team ID and Bundle ID:

curl https://your-auth0-domain/.well-known/apple-app-site-association

The response should look like:

{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": "TEAM_ID.BUNDLE_ID",
        "paths": ["/ios/BUNDLE_ID/*"]
      }
    ]
  }
}

If the file is missing or incorrect, verify in the Auth0 Dashboard that you have configured your Team ID and Bundle ID under Applications → Your App → Settings → iOS.

Step 3: Enable ephemeral sessions to isolate the browser session

Ephemeral sessions prevent the browser from sharing cookies with Safari, eliminating the shared session interference. Update your MAUI authentication code:

var client = new Auth0Client(new Auth0ClientOptions
{
    Domain = "your-tenant.auth0.com",
    ClientId = "your-client-id",
    RedirectUri = "https://yourcompany.com/callback",
    PostLogoutRedirectUri = "https://yourcompany.com/logout"
});

// For iOS, enable ephemeral session
#if IOS
    var options = new WebAuthenticatorOptions
    {
        PrefersEphemeralWebBrowserSession = true
    };
    // Pass options to the Auth0Client or WebAuthenticator call
#endif

Important: With ephemeral sessions enabled, the shared Safari cookie is not used. This means:

  • Users will not have SSO across your app and Safari
  • After logout, you must include prompt=login in the next login request to force a fresh login (otherwise the user may still be authenticated in the ephemeral session)

Step 4: Ensure logout callback URLs are configured separately

Navigate to Auth0 Dashboard → Applications → Your Application → Settings.

Verify that you have added your logout callback URL to Allowed Logout URLs (separate from Allowed Callback URLs):

https://yourcompany.com/logout

If you only configured login callbacks, the logout flow will not know where to redirect after clearing the session.

Step 5: Clear browser cache and test on a physical iOS device

  • On your development machine, clear Xcode's derived data: rm -rf ~/Library/Developer/Xcode/DerivedData/*
  • On the iOS device, go to Settings → [Your App Name] → Clear Cache (if available) or reinstall the app
  • Test on a physical iOS device, not the simulator (simulators have different AASA handling)

Step 6: If issues persist, add prompt=login to force fresh authentication

If you continue to see the login page remain after "Continue," add the prompt=login parameter to force a fresh authentication:

var authResult = await client.LoginAsync(new LoginRequest
{
    Parameters = new Dictionary<string, string>
    {
        { "prompt", "login" }
    }
});

Why This Approach Is Secure:

HTTPS universal links with associated domains are cryptographically verified by Apple. The AASA file is signed by Apple’s CDN, and the domain ownership is verified through the provisioning profile. This prevents application impersonation attacks that are possible with custom URI schemes, where any app can register the same scheme.

A similar issue regarding an iOS application not recognizing Auth0 associated domains has been published in the past on the community and can be a good resource for investigating the matter further.

Common Mistakes to Avoid:

  • Associated domain not added to provisioning profile: iOS cannot verify the domain ownership. Add webcredentials:yourcompany.com to the provisioning profile and re-sign the app.
  • AASA file not accessible or incorrectly formatted: iOS cannot find the app-to-domain mapping. Verify the file is at https://your-auth0-domain/.well-known/apple-app-site-association and contains your Team ID and Bundle ID.
  • Team ID or Bundle ID mismatch in AASA file: iOS rejects the domain association. Verify in Auth0 Dashboard that Team ID and Bundle ID match your app's configuration.
  • Not enabling ephemeral session on iOS: Shared cookies cause logout hangs and login failures. Set PrefersEphemeralWebBrowserSession = true for iOS.
  • Not configuring logout URL separately: Logout callback is not recognized. Add the logout URL to Allowed Logout URLs in the Dashboard.
  • Testing only on the simulator: Simulator AASA handling differs from physical devices. Always test on a physical iOS device.
  • Not clearing cache after configuration changes: Old AASA file is cached by iOS. Clear Xcode derived data and reinstall the app.

If Issues Persist:

  1. Check the iOS system logs for AASA validation errors: Open Xcode → Window → Devices and Simulators → Select your device → View Device Logs
  2. Verify the callback URL exactly matches the URL registered in the Dashboard (including protocol, domain, and path)
  3. Contact Auth0 Support with:
    • Your Auth0 tenant name
    • Your app's Bundle ID and Team ID
    • A HAR file of the callback flow (captured from Safari Developer Tools)
    • The exact iOS version and device model

Kind Regards,
Nik