所以我已经弄清楚了这里的根本原因。
在我们的身份验证方案中,我们在生态系统中有多个使用 azure AD SSO 的产品。由于“OnAuthorizationCodeReceived”仅在登录时调用,而不是在已保存有效登录 cookie 时调用,因此不会使用授权码填充令牌缓存。所以在这种情况下,这个场景的微软代码示例是完全错误的。发出身份验证质询不会导致调用“OnAuthorizationCodeReceived”,因为您已经持有有效的登录令牌。
所以,虽然它有点 litte 丑陋,但修复起来非常简单。强制注销,以便可以填充令牌缓存。
catch (AdalSilentTokenAcquisitionException e)
{
//in this case, it's possible there's no authorization code because the login cookie is from another session in
//the ecosystem. So in this scenario, force a logout so we can get a token into the tokencache
context.GetOwinContext().Authentication.SignOut(OpenIdConnectAuthenticationDefaults.AuthenticationType,
CookieAuthenticationDefaults.AuthenticationType);
sessionState.Abandon();
}
现在,因为我们在控制器之外使用此代码,并且我们调用了 await,所以 HttpContext 将为空。 HttpContext 中发生了一些严重的巫术,但我离题了。我们可以使用这个小变通方法来保持上下文:
var context = HttpContext.Current;
var sessionState = context.Session;
编辑:将应用程序部署到天蓝色应用服务时遇到了另一个问题。您要确保在 Azure 的“身份验证”面板中启用了 Azure AD 身份验证。在我切换它之前,我们遇到了一些无限登录循环问题。
编辑:
因此,在这种情况下强制注销真的不适合我。但是,我遇到了这个问题:
Azure Active Directory Graph API - access token for signed in user
我们能做的就是按照答案,调用AcquireTokenByAuthorizationCodeAsync(...),并确保使用4参数方法重载,其中最后一个参数是“https://graph.windows.net/”
现在,只要我们将授权代码存储在某处(在我的情况下存储在数据库表中)。在 AcquireTokenSilentAsync(...) 失败的情况下,我们应该能够获取给定用户的授权代码,并获取新的 GraphAPI 令牌。
现在可以通过无状态数据库调用备份您的全状态令牌缓存!
catch (AdalSilentTokenAcquisitionException e)
{
//in this case, the stateful cache is empty, so lets get the codeId from the DB
PersistentTokenCache pt = db.PersistentTokenCaches.Find(userObjectId);
if (pt != null && pt.token != null)
{
try
{
result = await ath.AcquireTokenByAuthorizationCodeAsync(pt.token,
new Uri(Startup.hostUri),
cc,
"https://graph.windows.net");
}
catch (AdalException ex)
{
Debug.WriteLine(ex.StackTrace);
//both authentication types have failed
pt.token = null;
await db.SaveChangesAsync();
context.GetOwinContext().Authentication.SignOut(OpenIdConnectAuthenticationDefaults.AuthenticationType,
CookieAuthenticationDefaults.AuthenticationType);
sessionState.Abandon();
return -1;
}
}
}