TokenAcquisition 失败时如何处理 MicrosoftIdentityWebChallengeUserException?

How can I handle MicrosoftIdentityWebChallengeUserException when TokenAcquisition fails?

我正在构建一个网络应用程序,当我重新启动应用程序并尝试使用 ITokenAcquisition.GetTokenForUserAsync

请求令牌时,我不断遇到以下错误

"One or more errors occurred. (IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user. See https://aka.ms/ms-id-web/ca_incremental-consent. )"

我正在使用 Microsoft.Identity.Web 对 Azure AD 用户进行身份验证。

当我检查令牌缓存时,重启应用后它是空的。如果用户已经从较早的会话登录,或者因为他们使用的是加入域的设备,他们似乎会绕过缓存。

如何强制重新验证或将令牌添加到缓存?

Startup.cs

       public void ConfigureServices(IServiceCollection services)
       {
           services.Configure<CookiePolicyOptions>(options =>
           {
               // This lambda determines whether user consent for non-essential cookies is needed for a given request.
               options.CheckConsentNeeded = context => true;
               options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
               // Handling SameSite cookie according to https://docs.microsoft.com/en-us/aspnet/core/security/samesite?view=aspnetcore-3.1
               options.HandleSameSiteCookieCompatibility();
           });
           // Sign-in users with the Microsoft identity platform
           services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
               .EnableTokenAcquisitionToCallDownstreamApi(new[] { "https://database.windows.net//.default" })
               .AddInMemoryTokenCaches();

           services.AddAuthorization(options =>
           {
               // By default, all incoming requests will be authorized according to the default policy
               options.FallbackPolicy = options.DefaultPolicy;
           });

           services.AddDbContext<MyDatabaseContext>(options =>
                   options.UseSqlServer(Configuration.GetConnectionString("MyAzureConnection")));

           services.AddRazorPages()
               .AddRazorRuntimeCompilation()
               .AddMvcOptions(o => o.Filters.Add(new AuthorizeFilter()))
               .AddMicrosoftIdentityUI();

       }

我请求令牌的 DbContext

        public MyDatabaseContext (ITokenAcquisition tokenAcquisition,
                            DbContextOptions<MyDatabaseContext> options)
                            : base(options)
        {
            _tokenAcquisition = tokenAcquisition;
            var token = _tokenAcquisition.GetAccessTokenForUserAsync(new[] {"https://database.windows.net//.default"});
            var connection = (SqlConnection)Database.GetDbConnection();
            connection.AccessToken = token.GetAwaiter().GetResult();
        }

我所有的 PageModels 都装饰有 [AuthorizeForScopes(ScopeKeySection = "AzureSQL:BaseUrl")]

这个error code意思是:

AADSTS65001: The user or administrator has not consented to use the application with ID '{appId}' named '{appName}'. Send an interactive authorization request for this user and resource.

缓解措施:

首先征得用户同意。如果您没有使用 .NET Core(没有任何 Web UI),请调用(仅一次)AcquireTokeninteractive。如果您使用的是 .NET 核心或不想执行 AcquireTokenInteractive,用户可以导航至 URL 以表示同意:https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={clientId}&response_type=code&scope=user.read。致电 AcquireTokenInteractiveapp.AcquireTokenInteractive(scopes).WithAccount(account).WithClaims(ex.Claims).ExecuteAsync();

就我而言,我在处理 .Net Core 3.1 Web 应用程序时遇到了 MicrosoftIdentityWebChallengeUserException。我在控制器操作中的代码:

string[] scopes = new string[] { "user.read", "https://storage.azure.com/user_impersonation" };
try
{
    ViewData["token"] = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes);
    return View();
}
catch (MicrosoftIdentityWebChallengeUserException ex)
{
    throw ex.MsalUiRequiredException;
}

注意 catch 块。 MicrosoftIdentityWebChallengeUserException 有一个 属性 可以访问 MsalUiRequiredException。我不得不抛出该异常以强制 Identity Web UI 再次显示同意 UI。我从 this link 那里得到了这个提示。查看其中的 MVC 控制器部分。它说,

AuthorizeForScopesAttribute inherits from ExceptionFilterAttribute which means that it processes the MSAL.NET MsalUiRequiredException to handle conditional access and incremental consent. This also means that if you catch MSAL exception, you should re-throw the caught MSAL exceptions so that the attribute can handle it

第二句话让我开心!它应该突出显示以节省我们的时间。

P.S。这是我准备 AZ204 时的示例应用程序。我一开始没有包含存储模拟范围,但后来添加了它。然后应用程序开始抛出上述异常,我不得不找到一种方法再次显示同意 UI。