다음을 통해 공유


영구 토큰 캐시가 없는 웹 애플리케이션에서 "AcquireTokenSilent에 계정 또는 로그인 힌트가 전달되지 않음" 오류

이 문서에서는 MSAL(Microsoft 인증 라이브러리) 또는 Microsoft ID 웹을 사용하여 웹 애플리케이션에서 발생하는 "AcquireTokenSilent에 계정 또는 로그인 힌트가 전달되지 않음" 오류에 대한 솔루션을 제공합니다.

증상

웹 애플리케이션이 MSAL 또는 Microsoft Identity Web을 사용하여 사용자를 인증하고 영구 토큰 캐시를 사용하지 않는다고 가정합니다. MSAL이 사용자 계정을 끌어와 토큰 캐시에서 자동으로 토큰을 획득하려고 하면 다음 오류 메시지가 표시됩니다.

AcquireTokenSilent에 계정 또는 로그인 힌트가 전달되지 않았습니다.

원인

이 문제는 MSAL이 기존 인증 쿠키를 기반으로 토큰 캐시에 더 이상 존재하지 않는 계정을 검색하기 때문에 발생합니다. 인증 쿠키는 대화형 로그인 후에만 만들어지고 사용자에 대한 정보를 포함합니다. 이 문제는 다음 시나리오에서 발생합니다.

  • 웹 애플리케이션이 다시 시작되었습니다.
  • 메모리 사용량이 많거나 설정된 비활성 기간으로 인해 메모리가 지워집니다.
  • MSAL에는 이전 항목을 자동으로 제거하는 기본 캐시 크기 제한이 있습니다.

SQL Server 또는 파일 기반 스토리지와 같은 지속성 위치에서 영구 토큰 캐시를 구현할 수 있습니다. 영구 토큰 캐시는 애플리케이션이 다시 시작되거나 메모리가 지워지는 경우에도 토큰이 유지되도록 합니다. 사용자 지정 영구 토큰 캐시를 구현하는 방법에 대한 자세한 내용은 토큰 캐시 serialization을 참조하세요.

쿠키 인증 이벤트를 구현하여 현재 로그인한 사용자가 MSAL 토큰 캐시에 있는지 여부를 확인할 수 있습니다. 사용자가 없는 경우 인증 쿠키를 거부하고 현재 사용자가 다시 로그인하도록 합니다.

MSAL을 사용하는 ASP.NET 웹 애플리케이션의 경우

쿠키 인증 이벤트를 만듭니다.

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();
        
                }
    
        }
    
    }

});

비고

쿠키 인증 이벤트를 구현하려면 웹 애플리케이션에서 다음 도우미 클래스와 Microsoft.Identity.Web.TokenCache NuGet 패키지를 설치해야 합니다.

  • MsalAppBuilder.cs
  • AuthenticationConfig.cs

MSAL을 사용하는 ASP.NET Core 웹 애플리케이션의 경우

  1. 사용자 지정 쿠키 인증 이벤트를 만듭니다.

    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. 사용자 지정 쿠키 인증 이벤트를 등록합니다.

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

Microsoft Identity Web을 사용하는 웹 애플리케이션의 경우

Microsoft ID 웹은 토큰 캐시를 관리하는 기본 제공 메커니즘을 제공합니다. 자세한 내용은 증분 동의 및 조건부 액세스 관리를 참조하세요. 이 문서가 문제를 해결하는 데 도움이 되지 않는 경우 사용자 지정 쿠키 인증 이벤트를 사용하여 인증 쿠키를 수동으로 지울 수 있습니다.

  1. 사용자 지정 쿠키 인증 이벤트를 만듭니다.

    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. 사용자 지정 쿠키 인증 이벤트를 등록합니다.

    // 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());
    

도움을 요청하십시오.

질문이 있거나 도움이 필요한 경우 지원 요청을 생성하거나Azure 커뮤니티 지원에 문의하세요. Azure 피드백 커뮤니티에 제품 피드백을 제출할 수도 있습니다.