Skip to content

Bug: Inconsistent WebAuthenticationBroker behavior on macOS vs Windows for localhost redirect URIs #35

Open

Description

@praveenkanike

Describe the bug

Problem Statement

On macOS, when using WebAuthenticationBroker with PreferNativeWebDialog = false, the authentication flow does not complete if the redirect URI is an http://localhost URL. After successful login and redirection, the web view remains open and AuthenticateAsync does not return the callback result.

The same implementation works as expected on Windows, where the web view closes and the callback URI is returned regardless of the PreferNativeWebDialog setting. This results in inconsistent cross-platform behavior.


Code Snippet

private async void BrokerAuthButton_SB_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
    try
    {
        string clientId = "46959941021-8l2ref5b4hmncdbiin9q6390l5h696e4.apps.googleusercontent.com";
        string redirectUri = "http://localhost:5000";
        string scope = "openid email profile";

        string codeVerifier = GenerateCodeVerifier();
        string codeChallenge = GenerateCodeChallenge(codeVerifier);

        string requestUri =
            "https://accounts.google.com/o/oauth2/v2/auth" +
            "?response_type=code" +
            $"&client_id={Uri.EscapeDataString(clientId)}" +
            $"&redirect_uri={Uri.EscapeDataString(redirectUri)}" +
            $"&scope={Uri.EscapeDataString(scope)}" +
            "&code_challenge_method=S256" +
            $"&code_challenge={codeChallenge}";

        var options = new WebAuthenticatorOptions(
            RequestUri: new Uri(requestUri),
            RedirectUri: new Uri(redirectUri)
        )
        {
            NonPersistent = true,
            PreferNativeWebDialog = false
        };

        var result = await WebAuthenticationBroker.AuthenticateAsync(this, options);

        if (result.CallbackUri != null)
        {
            var code = System.Web.HttpUtility.ParseQueryString(result.CallbackUri.Query)["code"];
            // handle code
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

To Reproduce

private async void BrokerAuthButton_SB_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
    try
    {
        string clientId = "46959941021-8l2ref5b4hmncdbiin9q6390l5h696e4.apps.googleusercontent.com";
        string redirectUri = "http://localhost:5000";
        string scope = "openid email profile";

        string codeVerifier = GenerateCodeVerifier();
        string codeChallenge = GenerateCodeChallenge(codeVerifier);

        string requestUri =
            "https://accounts.google.com/o/oauth2/v2/auth" +
            "?response_type=code" +
            $"&client_id={Uri.EscapeDataString(clientId)}" +
            $"&redirect_uri={Uri.EscapeDataString(redirectUri)}" +
            $"&scope={Uri.EscapeDataString(scope)}" +
            "&code_challenge_method=S256" +
            $"&code_challenge={codeChallenge}";

        var options = new WebAuthenticatorOptions(
            RequestUri: new Uri(requestUri),
            RedirectUri: new Uri(redirectUri)
        )
        {
            NonPersistent = true,
            PreferNativeWebDialog = false
        };

        var result = await WebAuthenticationBroker.AuthenticateAsync(this, options);

        if (result.CallbackUri != null)
        {
            var code = System.Web.HttpUtility.ParseQueryString(result.CallbackUri.Query)["code"];
            // handle code
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

Expected behavior

Webview should close once the defined redirection URL hit

Avalonia version

12.0

OS

macOS

Additional context

No response

Activity

  1. added theissue type on Apr 30, 2026
  2. maxkatz6 commented on Apr 30, 2026

    @maxkatz6
    Member

    It is expected, but also a documentation issue. API doesn't make it clear, that macOS/iOS prefers schema-driven redirects.

    On both macOS and iOS recommended and safe way for OAuth is to redirect this call to the system via ASWebAuthenticationSession.

    Limitation of ASWebAuthenticationSession is that it only works over scheme (http not supported). Which is why you need to define a URL with a special scheme unique to your application.
    PreferNativeWebDialog is useful to force a dialog instead of a browser, but that's not available on iOS.

    Something like is necessary for native ASWebAuthenticationSession:

    var redirectUri = OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() ? new Uri("my-app://") : new Uri("http://localhost/");

    And then configure this scheme with CFBundleURLTypes in the Info.plist, so iOS can associate your app with it:

        <key>CFBundleURLTypes</key>
        <array>
            <dict>
                <key>CFBundleURLSchemes</key>
                <array>
                    <string>my-app</string>
                </array>
            </dict>
        </array>
  3. changed the issue type fromtoon Apr 30, 2026
  4. changed the issue type fromtoon Apr 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions