我已经启用了azure ad的身份验证,以下是来自MS的一些示例应用程序。然后,我也使用下面的授权语句,这样我的应用程序应该被锁定,除非用户经过身份验证。我在测试环境中的问题是,如果我重新启动IIS express,那么当它重新启动时,如果浏览器仍然打开,我不需要重新登录。我可以公开浏览我的应用程序,但是当任何与MS Graph相关的函数被调用时,它会出现错误:ErrorCode: user_null Microsoft.Identity.Client.MsalUiRequiredException:没有帐户或登录提示被传递给AcquireTokenSilent调用。所以,如果我的应用程序认为我仍然被授权,但我真的不是因为MS图api调用失败,因为令牌相关的问题。如果我强迫自己登出,然后再登录,一切都可以正常工作。对于我的活动站点,如果用户在一段时间内不活动,但浏览器仍然打开,则会发生同样的问题,并且他们不会被迫重新登录,因此这些问题再次发生,直到他们强制注销并重新登录。在这些问题出现之前,我设置错误或需要添加什么来强制重新登录?或者我可以在不强制用户重新登录的情况下保持令牌工作吗?
// Add services to the container.
builder.Services.AddRazorPages().AddRazorPagesOptions(options =>
{
options.Conventions.AllowAnonymousToFolder("/Login");
options.Conventions.AuthorizeFolder("/");
options.Conventions.AuthorizeFolder("/files");
});
//authentication pipline
builder.Services.AddHttpContextAccessor();
var initialScopes = builder.Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
builder.Configuration.Bind("AzureAd", options);
options.Events = new OpenIdConnectEvents
{
//Tap into this event to add a UserID Claim to a new HttpContext identity
OnTokenValidated = context =>
{
//This query returns the UserID from the DB by sending the email address in the claim from Azure AD
string query = "select dbo.A2F_0013_ReturnUserIDForEmail(@Email) as UserID";
string connectionString = builder.Configuration.GetValue<string>("ConnectionStrings:DBContext");
string signInEmailAddress = context.Principal.FindFirstValue("preferred_username");
using (var connection = new SqlConnection(connectionString))
{
var queryResult = connection.QueryFirst(query, new { Email = signInEmailAddress });
var claims = new List<Claim>
{
new Claim("UserID", queryResult.UserID.ToString())
};
var appIdentity = new ClaimsIdentity(claims);
context.Principal.AddIdentity(appIdentity);
}
return Task.CompletedTask;
},
};
})
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
//Add Transient Services
builder.Services.AddTransient<IOneDrive, OneDrive>();
builder.Services.AddControllers(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
builder.Services.AddRazorPages()
.AddMicrosoftIdentityUI();
然后在我所有的控制器中我使用:
[AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")]
添加
var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(initialScopes);
之前我的图形API调用修复我的问题。然而,我觉得我不应该每次都调用这个,只在令牌过期时调用。那么有没有办法检查令牌是否过期?
有两件事对我很有效。如果使用以下命令发生错误,则尝试手动获取令牌:
var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(initialScopes);
另一个似乎同样有效的解决方案是添加以下捕获:
try
{
Console.WriteLine($"{svcex}");
string claimChallenge = WwwAuthenticateParameters.GetClaimChallengeFromResponseHeaders(svcex.ResponseHeaders);
_consentHandler.ChallengeUser(initialScopes, claimChallenge);
}
catch (Exception ex2)
{
_consentHandler.HandleException(ex2);
}
我不知道什么同意处理程序提供更多的信息,为什么这工作,但我会更新我的答案,一旦我这样做。