.net 当TokenAcquisition失败时,如何处理MicrosoftIdentityWebChallengeUserException?

.net 当TokenAcquisition失败时,如何处理MicrosoftIdentityWebChallengeUserException?,.net,azure-active-directory,azure-web-app-service,msal,.net-5,.net,Azure Active Directory,Azure Web App Service,Msal,.net 5,我正在构建一个Web应用程序,当我重新启动应用程序并尝试使用ITokenAcquisition.GetTokenFourserAsync “出现一个或多个错误。(IDW10502:由于用户的质询而引发MsalUiRequiredException。请参阅)。” 我正在使用Microsoft.Identity.Web根据Azure广告对用户进行身份验证 当我检查令牌缓存时,它在重新启动应用程序后为空。如果用户已经从以前的会话登录,或者因为他们正在使用加入域的设备,那么他们似乎会绕过缓存 如何强制重

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

“出现一个或多个错误。(IDW10502:由于用户的质询而引发MsalUiRequiredException。请参阅)。”

我正在使用Microsoft.Identity.Web根据Azure广告对用户进行身份验证

当我检查令牌缓存时,它在重新启动应用程序后为空。如果用户已经从以前的会话登录,或者因为他们正在使用加入域的设备,那么他们似乎会绕过缓存

如何强制重新验证或向缓存中添加令牌

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

       }
public void配置服务(IServiceCollection服务)
{
配置(选项=>
{
//此lambda确定给定请求是否需要非必要cookie的用户同意。
options.checkApprovered=context=>true;
options.MinimumSameSitePolicy=SameSiteMode.Unspecified;
//根据标准处理SameSite cookiehttps://docs.microsoft.com/en-us/aspnet/core/security/samesite?view=aspnetcore-3.1
options.HandleSameSiteCookieCompatibility();
});
//使用Microsoft identity platform登录用户
services.AddMicrosoftIdentityWebAppAuthentication(配置)
.EnableTokenAcquisitionToCallDownstreamMapi(新[]{”https://database.windows.net//.default" })
.AddInMemoryTokenCaches();
services.AddAuthorization(选项=>
{
//默认情况下,将根据默认策略授权所有传入请求
options.FallbackPolicy=options.DefaultPolicy;
});
services.AddDbContext(选项=>
options.UseSqlServer(Configuration.GetConnectionString(“MyAzureConnection”));
services.AddRazorPages()
.AddRazorRuntimeCompilation()文件
.addmvcopions(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();
        }
公共MyDatabaseContext(ITokenAcquisition tokenAcquisition, DbContextOptions(选项) :基本(选项) { _tokenAcquisition=tokenAcquisition; var token=\u tokenAcquisition.GetAccessTokenForUserAsync(新[]{”https://database.windows.net//.default"}); var connection=(SqlConnection)Database.GetDbConnection(); connection.AccessToken=token.GetAwaiter().GetResult(); } 我的所有页面模型都用
[AuthorizeForScopes(scopekeyssection=“AzureSQL:BaseUrl”)]
装饰,这意味着:

AADSTS65001:用户或管理员尚未同意使用 ID为“{appId}”且名为“{appName}”的应用程序。发送一个交互式 此用户和资源的授权请求

缓解措施:
首先获得用户同意。如果您没有使用.NET Core(它没有任何Web UI),请调用(仅一次)
AcquireTokeninteractive
。如果您正在使用.NET core或不想执行
AcquireTokenInteractive
,用户可以导航到URL以给予同意:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={clientId}&response\u type=code&scope=user.read
。调用
AcquireTokenInteractive
app.AcquireTokenInteractive(作用域).WithAccount(帐户).WithClaims(例如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
具有访问
MSAlluiRequiredException
的属性。我不得不抛出该异常以强制Identity Web UI再次显示同意UI。我是从你那里得到这个消息的。请看其中的MVC控制器部分。上面说,

AuthorizeForScopesAttribute继承自ExceptionFilterAttribute,这意味着它处理MSAL.NET MsalUiRequiredException以处理条件访问和增量同意。这还意味着,如果捕获MSAL异常,则应重新抛出捕获的MSAL异常,以便属性能够处理它

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


另外,这是我在准备AZ204时的示例应用程序。起初我没有包括存储模拟范围,但后来添加了它。然后应用程序开始抛出上述异常,我必须找到一种方法再次显示同意用户界面。

谢谢,这为我指明了正确的方向。我大量借用了Microsoft.Identity.Web中的一个服务,其中包含ChallengeUser方法(以下链接)。