Repository navigation
Bug: Inconsistent WebAuthenticationBroker behavior on macOS vs Windows for localhost redirect URIs #35
Copy link
Copy link
Open
Description
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
Reactions are currently unavailable
Activity
maxkatz6 commentedon Apr 30, 2026
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:And then configure this scheme with CFBundleURLTypes in the Info.plist, so iOS can associate your app with it: