I am building a .NET MAUI mobile app that uses MSAL.NET to authenticate with Azure AD B2C.
On iOS TestFlight builds, when I call AcquireTokenInteractive(), the system browser (ASWebAuthenticationSession) never opens.
My loading UI appears, but the B2C login page never shows.
Eventually, MSAL throws:
MsalClientException: authentication_canceled
On iOS Debug builds, everything works perfectly:
- Browser opens
- B2C login page loads
- Redirect returns
- Authentication succeeds
So the issue happens only in TestFlight, not in Debug mode.
CFBundleURLTypes
CFBundleTypeRole
Editor
CFBundleURLName
msal-
CFBundleURLSchemes
msal
LSApplicationQueriesSchemes
msauth
msauthv2
msauthv3
msauthv3.0
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
return true;
}
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
if (!NSUserDefaults.StandardUserDefaults.BoolForKey("firstLaunchDone"))
{
var pcaWrapper = (IPcaWrapper)Current.Services.GetService(typeof(IPcaWrapper));
var pca = ((PcaWrapper)pcaWrapper).PublicClientApplication;
var accounts = pca.GetAccountsAsync().Result;
foreach (var acc in accounts)
pca.RemoveAsync(acc).Wait();
NSUserDefaults.StandardUserDefaults.SetBool(true, "firstLaunchDone");
}
return base.FinishedLaunching(app, options);
}
public PcaWrapper(IConfiguration configuration)
{
settings = configuration.GetRequiredSection("Settings").Get();
Scopes = BuildScopes(settings);
string redirectUri = string.IsNullOrWhiteSpace(PlatformConfig.Instance.RedirectUri)
? settings.RedirectUri //
: PlatformConfig.Instance.RedirectUri;
PlatformConfig.Instance.RedirectUri = redirectUri;
authority = BuildAuthority(settings); // https:///
PublicClientApplication = PublicClientApplicationBuilder
.Create(settings.ClientId) //
.WithB2CAuthority(authority)
.WithRedirectUri(redirectUri)
.WithIosKeychainSecurityGroup("com.microsoft.adalcache")
.Build();
}
private async Task AcquireTokenInteractiveInternalAsync(string[] scopes)
{
var builder = PublicClientApplication
.AcquireTokenInteractive(scopes)
.WithB2CAuthority(authority)
.WithUseEmbeddedWebView(true);
if (PlatformConfig.Instance.ParentWindow != null)
{
builder = builder.WithParentActivityOrWindow(PlatformConfig.Instance.ParentWindow);
}
return await MainThread.InvokeOnMainThreadAsync(() => builder.ExecuteAsync());
}
"Settings": {
"ClientId": "",
"TenantId": "",
"Instance": "https://.b2clogin.com",
"Domain": ".onmicrosoft.com",
"SignUpSignInPolicyId": "",
"RedirectUri": "msal://auth",
"Scopes": [
{ "Value": "openid" },
{ "Value": "offline_access" }
]
}
- App launches
- I call
AcquireTokenInteractive() - My loading UI appears
- System browser never opens
- No login page
- No redirect
- Eventually MSAL throws
authentication_canceled
This does not happen in Debug mode.
- Redirect URI registered in Azure B2C
- Matching scheme added to Info.plist
- Keychain access group set (
com.microsoft.adalcache) - AppDelegate.OpenUrl implemented
- No SceneDelegate (MAUI default)
- Tried embedded + system browser
- TestFlight entitlements appear correct
Still the browser does not launch.
Why does ASWebAuthenticationSession fail to open only in TestFlight builds, and could this be caused by missing plist capabilities, redirect URI format issues, required entitlements, or any TestFlight-specific restrictions affecting MSAL.NET MAUI interactive login?
Any help would be greatly appreciated.