Skip to content

[Bug] AcquireTokenInteractive localhost redirection fails for all attempts after the first successful authentication #5455

@phw198

Description

@phw198

Library version used

4.73.1.0

.NET version

Windows application targeting .NET Framework 4.6.2

Scenario

PublicClient - desktop app

Is this a new or an existing app?

The app is in production, and I have upgraded to a new version of MSAL

Issue description and reproduction steps

I am successfully creating an PublicClientApplicationBuilder that opens the system default browser for authentication and redirects back to localhost as expected. However, if I call exactly the same code more than once, all subsequent attempts open the browser, but after authentication the localhost redirect fails with "localhost refused to connect".

Using netstat -ano | find "LISTEN" I can see the random ephemeral port open and listening during authentication and this disappears after the redirect; the port number matches the browser URL, eg
TCP [::]:65457 [::]:0 LISTENING 4
http://localhost:65457/?code=xx&client_info=xx&state=xx

The only way to get the properly functioning again is to close the application and start a new instance, so I suspect the local socket is not being released and as there is no Dispose() method for IPublicClientApplication there seems no way to do this through code?

Therefore, this makes for a poor use experience as the browser makes it look like it's failed.

Two points of note:-

  1. In my application code where I create storage cache for the token file, even if I delete this and call oAuthApp.RemoveAsync() on all the accounts held, despite the apparent failure, subsequent Graph calls are actually successful.
  2. If intercepting traffic with Fiddler, all attempts are always successful.

Relevant code snippets

#
private Microsoft.Identity.Client.IPublicClientApplication oAuthApp;

private async System.Threading.Tasks.Task<bool> foo() {
    oAuthApp = Microsoft.Identity.Client.PublicClientApplicationBuilder.Create(clientId)
        .WithAuthority("https://login.microsoftonline.com/common")
        .WithRedirectUri("http://localhost")
        .Build();

    String[] scopes = new string[] { "user.read", "Calendars.ReadWrite", "Calendars.ReadWrite.Shared" };
    Microsoft.Identity.Client.IAccount firstAccount = (await oAuthApp.GetAccountsAsync()).FirstOrDefault();

    Microsoft.Identity.Client.AuthenticationResult authResult = await oAuthApp.AcquireTokenInteractive(scopes)
                .WithAccount(firstAccount)
                .WithPrompt(Microsoft.Identity.Client.Prompt.SelectAccount)
                .WithUseEmbeddedWebView(false)
                .ExecuteAsync();
    return true;
}

public void test() {
    var bar = System.Threading.Tasks.Task.Run(async () => { await foo(); });
    bar = System.Threading.Tasks.Task.Run(async () => { await foo(); });
}

Expected behavior

Any subsequent attempts to authenticate following the initial one, should also successfully redirect to the localhost port and give a proper "this window can now be closed" message (not "connection refused").

Identity provider

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

Regression

No response

Solution and workarounds

  1. Close the application and reopen - not really a workaround
  2. Intercept local traffic with Fiddler - not a production solution.

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