Compartilhar via


Erro "Nenhuma conta ou dica de logon foi passada para o AcquireTokenSilent" em aplicativos Web sem cache de token persistente

Este artigo oferece soluções para o erro "Nenhuma conta ou dica de logon foi passada para o AcquireTokenSilent" que ocorre em um aplicativo Web usando a MSAL (Biblioteca de Autenticação da Microsoft) ou o Microsoft Identity Web.

Sintomas

Suponha que seus aplicativos Web autentiquem usuários usando MSAL ou Microsoft Identity Web e não usem caches de token persistentes. Quando o MSAL tenta extrair uma conta de usuário e adquirir um token de forma discreta de seu armazenamento de token, a seguinte mensagem de erro é exibida:

Nenhuma conta ou dica de logon foi passada para o AcquireTokenSilent

Motivo

Esse problema ocorre porque a MSAL procura uma conta que não existe mais no cache de token com base em um cookie de autenticação existente. O cookie de autenticação é criado somente após uma entrada interativa e contém informações sobre o usuário. Esse problema ocorre nos seguintes cenários:

  • O aplicativo Web foi reiniciado.
  • A memória é liberada devido ao uso elevado de memória ou após um período de inatividade determinado.
  • A MSAL tem um limite de tamanho de cache padrão que remove automaticamente entradas mais antigas.

Você pode implementar um cache de token persistente em um local durável, como o SQL Server ou o armazenamento baseado em arquivo. Um cache de token persistente garante que os tokens sejam retidos mesmo quando o aplicativo for reiniciado ou a memória for limpa. Para obter mais informações sobre como implementar um cache de token persistente personalizado, consulte a serialização do cache de token.

Você pode implementar um evento de autenticação de cookie para validar se o usuário conectado atualmente está presente no cache de token MSAL. Se o usuário não estiver presente, rejeite o cookie de autenticação e force o usuário atual a entrar novamente.

Para aplicativos Web ASP.NET usando MSAL

Criar um evento de autenticação de cookie:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    Provider = new CookieAuthenticationProvider()
    {
        OnValidateIdentity = async context =>
        {
            IConfidentialClientApplication clientApp = MsalAppBuilder.BuildConfidentialClientApplication();
        
                var signedInUserIdentity = new ClaimsPrincipal(context.Identity);
        
                if (await clientApp.GetAccountAsync(signedInUserIdentity.GetAccountId()) == null)
        
                {
        
                    context.RejectIdentity();
        
                }
    
        }
    
    }

});

Observação

Para implementar um evento de autenticação de cookie, o aplicativo Web deve instalar as seguintes classes auxiliares e o Microsoft.Identity.Web.TokenCache pacote NuGet:

  • MsalAppBuilder.cs
  • AuthenticationConfig.cs

Para aplicações Web ASP.NET Core usando MSAL

  1. Criar um evento de autenticação de cookie personalizado:

    using Microsoft.AspNetCore.Authentication.Cookies;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Identity.Client;
    using System.Threading.Tasks;
    using System.Security.Claims;
    
    namespace SampleApp.Services
    {
        internal class RejectSessionCookieWhenAccountNotInCacheEvents : CookieAuthenticationEvents
        {
            public async override Task ValidatePrincipal(CookieValidatePrincipalContext context)
            {
                var msalInstance = context.HttpContext.RequestServices.GetRequiredService();
                IConfidentialClientApplication msalClient = msalInstance.GetClient();
    
                        var accounts = await msalClient.GetAccountsAsync();
    
                        var account = await msalClient.GetAccountAsync(accounts.FirstOrDefault());
    
                        if (account == null)
    
                        {
    
                            context.RejectPrincipal();
    
                        }
    
                        await base.OnValidatePrincipal(context);
    
                }
    
        }
    
    }
    
  2. Registre o evento de autenticação de cookie personalizado:

    Services.Configure<CookieAuthenticationOptions>(cookieScheme, options=>options.Events=new RejectSessionCookieWhenAccountNotInCacheEvents());
    

Para aplicativos Web usando o Microsoft Identity Web

O Microsoft Identity Web fornece mecanismos internos para gerenciar caches de token. Para obter mais informações, consulte Gerenciando o consentimento incremental e o acesso condicional. Se este documento não ajudar você a resolver o problema, você poderá limpar manualmente o cookie de autenticação usando um evento de autenticação de cookie personalizado:

  1. Criar um evento de autenticação de cookie personalizado:

    using Microsoft.AspNetCore.Authentication.Cookies;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Identity.Client;
    using Microsoft.Identity.Web;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace SampleApp.Services
    {
        internal class RejectSessionCookieWhenAccountNotInCacheEvents : CookieAuthenticationEvents
        {
            public async override Task ValidatePrincipal(CookieValidatePrincipalContext context)
            {
                try
                {
                    var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService();
                    string token = await tokenAcquisition.GetAccessTokenForUserAsync(
                    scopes: new[] { "profile" },
                    user: context.Principal);
                }
                catch (MicrosoftIdentityWebChallengeUserException ex)
                when (AccountDoesNotExistInTokenCache(ex))
                {
                    context.RejectPrincipal();
                }
            }
            /// <summary>
            /// Is the exception due to no account in the token cache?
            /// </summary>
            /// <param name="ex">Exception thrown by <see cref="ITokenAcquisition"/>.GetTokenForXX methods.</param>
            /// <returns>A boolean indicating if the exception relates to the absence of an account in the cache.</returns>
            private static bool AccountDoesNotExistInTokenCache(MicrosoftIdentityWebChallengeUserException ex)
            {
                return ex.InnerException is MsalUiRequiredException
    
                       && (ex.InnerException as MsalUiRequiredException).ErrorCode == "user_null";
    
            }
    
        }
    
    }
    
  2. Registre o evento de autenticação de cookie personalizado:

    // Add Microsoft Identity Web
    services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                        .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
                            .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
                               .AddMicrosoftGraph(Configuration.GetSection("GraphBeta"))
                               .AddInMemoryTokenCaches();
    
    // Register the Custom Cookie Authentication event
    Services.Configure<CookieAuthenticationOptions>(cookieScheme, options=>options.Events=new RejectSessionCookieWhenAccountNotInCacheEvents());
    

Entre em contato conosco para obter ajuda

Se você tiver dúvidas ou precisar de ajuda, crie uma solicitação de suporte ou peça ajuda à comunidade de suporte do Azure. Você também pode enviar comentários sobre o produto para a comunidade de comentários do Azure.