Skip to content

[Bug] WAM broker on Windows selects wrong account despite tenant/account pinning; Android broker correct #5737

@hyigit-adelcon

Description

@hyigit-adelcon

Library version used

4.82.1

.NET version

Summary

When using MSAL.NET with the Windows broker (WAM), silent token acquisition sometimes returns a token for a different OS-known account than the one explicitly requested, even though the tenant is pinned and an explicit IAccount is passed to AcquireTokenSilent. The same code and app registration with the Android broker (Microsoft Authenticator) consistently returns the correct account. This appears to be a WAM-specific account selection regression/bug.

Environment

  • MSAL packages:
    • Microsoft.Identity.Client = 4.82.1
    • Microsoft.Identity.Client.Broker = 4.82.1
    • Microsoft.Identity.Client.Extensions.Msal = 4.82.1
  • OS / Device:
    • Windows 11 (repro)
    • Android 24 (works as expected)
  • .NET target: 10
  • App type: Desktop public client using WAM broker (WithBroker)
  • Scopes: https://api.businesscentral.dynamics.com/.default

Minimal Code Sample

var tenantId = "<TENANT_ID>";
var clientId = "<CLIENT_ID>";
var scopes   = new[] { "https://api.businesscentral.dynamics.com/.default" };

var pca = PublicClientApplicationBuilder
    .Create(clientId)
    .WithAuthority($"https://login.microsoftonline.com/organizations")
    .WithDefaultRedirectUri()
    .WithBroker(new BrokerOptions(BrokerOptions.OperatingSystems.Windows))
    .Build();

// Optional: file cache if desired
// var storageProps = new StorageCreationPropertiesBuilder("MSAL.dat", "<CACHE_DIR>").Build();
// var cacheHelper  = await MsalCacheHelper.CreateAsync(storageProps);
// cacheHelper.RegisterCache(pca.UserTokenCache);

// A) Interactive (force account picker)
var interactive = pca.AcquireTokenInteractive(scopes)
    .WithTenantId(tenantId);
    .WithPrompt(Prompt.SelectAccount);

var resultInteractive = await interactive.ExecuteAsync();

// B) Silent for the *same* account
var accounts = await pca.GetAccountsAsync();
var account  = accounts.FirstOrDefault(a => a.Username.Equals("<INTENDED_UPN>", StringComparison.OrdinalIgnoreCase));

var resultSilent = await pca.AcquireTokenSilent(scopes, account)
    .WithTenantId(tenantId)
    .ExecuteAsync();

// On Windows WAM, resultSilent may carry claims for a *different* identity

Expected Behavior

On Windows (WAM), when the tenant is pinned and a specific IAccount is provided to AcquireTokenSilent, MSAL/WAM should return a token for that exact account—parity with the observed behavior on Android broker.

Actual Behavior

On Windows (WAM), the returned token’s identity sometimes corresponds to a different OS-known account (e.g., a technician/guest identity), even though:

  • The authority/tenant is pinned, and
  • The explicit IAccount passed to AcquireTokenSilent matches the intended user, and
  • Prompt.SelectAccount was used during interactive acquisition.

Workarounds Tried

  • Tenant pinning at PCA build and per-request .WithTenantId(tenantId) → still repro.
  • Passing explicit IAccount to AcquireTokenSilent(scopes, account) → still repro.
  • Prompt.SelectAccount + WithLoginHint during interactive → still repro.
  • Removing the unwanted account from MSAL cache → still repro when that account remains known to the OS/WAM.
  • Disabling broker (browser fallback) → no repro (correct account is used consistently).

Logs

Verbose MSAL logs with PII enabled show the requested HomeAccountId/Username versus the identity that WAM ultimately resolves for the silent call. Redacted logs can be attached privately if needed.

Why This Seems Like a Bug

Documentation indicates that apps can deterministically control which tenant/account is used via tenant pinning and by passing the desired IAccount to AcquireTokenSilent. Returning a token for a different identity under WAM contradicts these expectations, especially given that Android broker behaves correctly with the same inputs.

Related Docs / References (context)

Ask

  • Please confirm whether WAM is expected to always honor the explicit IAccount and tenant pinning during silent acquisition.
  • If yes, this appears to be a bug; guidance/workaround or a fix would be appreciated.
  • If by design, could documentation clarify how WAM resolves accounts when multiple identities are present and how apps can reliably override that to achieve parity with Android broker?

Scenario

PublicClient - desktop app

Is this a new or an existing app?

This is a new app or experiment

Issue description and reproduction steps

Steps to Reproduce

  1. Build a public client with WAM broker enabled and a "organizations" authority.
  2. Perform an interactive acquisition and force account selection
  3. Use .WithTenantId(tenantId) on requests
  4. Call AcquireTokenSilent(scopes, account) with the exact IAccount returned by GetAccountsAsync().
  5. Inspect the access token claims (email, unique_name, name).
  6. On Windows (WAM), the token occasionally belongs to a different identity (another OS-known account) than the one passed to AcquireTokenSilent.
  7. On Android broker, the same code returns the correct identity consistently.

Relevant code snippets

Expected behavior

No response

Identity provider

Microsoft Entra ID (Work and School accounts and Personal Microsoft accounts)

Regression

No response

Solution and workarounds

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions