Search code examples
c#azureexchangewebservicesazure-ad-msal

MSAL AcquireTokenInteractive redirects browser to unavaible localhost


We are using AcquireTokenInteractive to connect to EWS 365 like this:

// using Microsoft.Identity.Client 4.61.1

var pca = PublicClientApplicationBuilder
         .CreateWithApplicationOptions(pcaOptions) // userId, tennantid
         .WithDefaultRedirectUri()
         .Build();
...

var result = await pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync();

This is more or less what the example code does, that you can find somewhere in Entra. We did this following this explanation Authentication and EWS in Exchange.

This is working fine, we get the token and everything. However the browser that was used to do the auth allways does a redirect to some http://localhost:SOMEPORT that fails and thus shows an error message.

What is it that we are doing wrong here? We did not specify any rediect uris in the portal and if we omit the WithDefaultRedirectUri() we get an error

Microsoft.Identity.Client.MsalClientException: "Only loopback redirect uri is supported, but urn:ietf:wg:oauth:2.0:oob was found. Configure http://localhost or http://localhost:port both during app registration and when you create the PublicClientApplication object. See https://aka.ms/msal-net-os-browser for details"

or similiar depending if its on a wpf app or unit test.

Since all we care about the token (which is working), that failed browser redirect will just confuse the user. How do we get rid of it?


Solution

  • Initially, I too got same error when I removed WithDefaultRedirectUri() line from code while getting token with interactive flow:

    enter image description here

    To resolve the error, make sure to add http://localhost as redirect URI in "Mobile and desktop applications" platform while using interactive flow for token generation:

    enter image description here

    In my case, I ran below modified code in .NET 8 console app by including redirect URI and got login screen to pick account:

    using Microsoft.Identity.Client;
    
    class Program
    {
        private static string _clientId = "appId";
        private static string _tenantId = "tenantId";
    
    
        static async Task Main(string[] args)
        {
            var pcaOptions = new PublicClientApplicationOptions
            {
                ClientId = _clientId,
                TenantId = _tenantId
            };
    
            var redirectUri = "http://localhost";
    
            var pca = PublicClientApplicationBuilder
                .CreateWithApplicationOptions(pcaOptions)
                .WithRedirectUri(redirectUri)
                .Build();
    
            var ewsScopes = new string[] { "https://outlook.office365.com/EWS.AccessAsUser.All" };
    
            try
            {
                var accounts = await pca.GetAccountsAsync();
                AuthenticationResult result;
    
                if (accounts.Any())
                {
                    result = await pca.AcquireTokenSilent(ewsScopes, accounts.FirstOrDefault())
                        .ExecuteAsync();
                }
                else
                {
                    result = await pca.AcquireTokenInteractive(ewsScopes)
                        .ExecuteAsync();
                }
    
                Console.WriteLine("Access Token:");
                Console.WriteLine(result.AccessToken);
            }
            catch (MsalException msalEx)
            {
                Console.WriteLine($"Error Acquiring Token: {msalEx}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error Acquiring Token: {ex}");
            }
        }
    }
    

    Pick an account:

    enter image description here

    Once the authentication is successful, user will be redirected to this page in browser:

    enter image description here

    When I checked the output console now, I got access token successfully like this:

    enter image description here

    To confirm that, I decoded the access token in jwt.ms website where it has aud and scp claims as below:

    enter image description here

    Reference:

    Default reply URI - Microsoft Authentication Library for .NET | Microsoft