MSAL: Getting null everytime when AcquireTokenSilent in ASP.NET MVC Classic

Viewed 101

I am working on ASP.Net MVC 4.7.2 (classics). Using Azure AD Authenticaiton (Microsoft Identity platform) for authentication and for Web Api authorization.

When using code flow to get the api resource I wan to store the token and get it silently when needed. I got the code from MSAL team from Git. But code doesn't work. Whenever I acquire the code silently the I get the error. When I debugged the issue I found that IAccounet is return null see the following line that returns null.

 IAccount account = 
   _MsalAppBuilder.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId()).Result;

Since account is null therefore the next line of code throws error. Therefore nt aoo us unable to work

AuthenticationResult result = app.AcquireTokenSilent(scopes, account).ExecuteAsync().Result;

As I debugged the issue, I could not find any reason why it is happening and even after extensive search. However what I found that in the Startup class, the method AcquireAccessToken never hit, thus the token does not save.

Can something help understand it please.

MSAL class:

 public static class MsalAppBuilder
    {
        public static string GetAccountId(this ClaimsPrincipal claimsPrincipal)
        {
            string oid = claimsPrincipal.GetObjectId();
            string tid = claimsPrincipal.GetTenantId();
            return $"{oid}.{tid}";
        }

        private static IConfidentialClientApplication clientapp;

        public static IConfidentialClientApplication BuildConfidentialClientApplication()
        {
            if (clientapp == null)
            {
                clientapp = ConfidentialClientApplicationBuilder.Create(Globals.clientId)
                      .WithClientSecret(Globals.clientSecret)
                      .WithRedirectUri(Globals.redirectUri)
                      .WithAuthority(new Uri(Globals.authority))
                      .Build();

                // In-memory distributed token cache

                clientapp.AddDistributedTokenCache(services =>
                {
                    services.AddDistributedMemoryCache();
                    services.Configure<MsalDistributedTokenCacheAdapterOptions>(o =>
                    {
                        o.Encrypt = true;
                    });
                });
            }
            return clientapp;
        }

        //this was commented already
        /*
                        // Could also use other forms of cache, like Redis
                        // See https://aka.ms/ms-id-web/token-cache-serialization
                        clientapp.AddDistributedTokenCache(services =>
                        {
                            services.AddStackExchangeRedisCache(options =>
                            {
                                options.Configuration = "localhost";
                                options.InstanceName = "SampleInstance";
                            });
                        });
        */

        public static async Task RemoveAccount()
        {
            BuildConfidentialClientApplication();

            var userAccount = await clientapp.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId());
            if (userAccount != null)
            {
                await clientapp.RemoveAsync(userAccount);
            }
        }

startup class:

public void Configuration(IAppBuilder app)
    {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
        //app.UseCookieAuthentication(new CookieAuthenticationOptions());
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
           // CookieManager = new SystemWebCookieManager()
            AuthenticationType = "Cookies",
            CookieManager = new Microsoft.Owin.Host.SystemWeb.SystemWebChunkingCookieManager()
        });
        app.UseOpenIdConnectAuthentication(
        new OpenIdConnectAuthenticationOptions
        {
            // Sets the ClientId, authority, RedirectUri as obtained from web.config
            ClientId = clientId,
            Authority = authority,
            RedirectUri = redirectUri,
            // PostLogoutRedirectUri is the page that users will be redirected to after sign-out. In this case, it is using the home page
            PostLogoutRedirectUri = redirectUri,
            Scope = OpenIdConnectScope.OpenIdProfile,
            // ResponseType is set to request the code id_token - which contains basic information about the signed-in user
            //ResponseType = OpenIdConnectResponseType.CodeIdToken,
            ResponseType = OpenIdConnectResponseType.CodeIdToken,

            // OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to OnAuthenticationFailed method
            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                AuthorizationCodeReceived = OnAuthorizationCodeReceived,
                AuthenticationFailed = OnAuthenticationFailed
            }
        }
    );
    }




    private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
    {          
        var scopes = Globals.scopeTravelAuthApi;
        IConfidentialClientApplication clientApp = MsalAppBuilder.BuildConfidentialClientApplication();
        AuthenticationResult result = await clientApp.AcquireTokenByAuthorizationCode(new[] { scopes}, context.Code).ExecuteAsync().ConfigureAwait(true);
         context.HandleCodeRedemption(result.AccessToken, result.IdToken);

    }

    /// <summary>
    /// Handle failed authentication requests by redirecting the user to the home page with an error in the query string
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
        {
            context.HandleResponse();
            context.Response.Redirect("/?errormessage=" + context.Exception.Message);
            return Task.FromResult(0);
        }
    }

By the way, I have checked all the settings related to Azure AD they ar correct. In the same app I am accessing Graph API which is working fine only issue is getting the access token silently.

0 Answers
Related