AAD 图 API returns 404 在调用 AcquireTokenAsync 之后,但在调用 AcquireTokenSilentAsync 之后没有
AAD Graph API returns 404 after call to AcquireTokenAsync, but not after call to AcquireTokenSilentAsync
所以我有一个调用图形的应用程序 API。
请参阅以下代码段:
调用 try (AquireTokenSilent) 时,Web 请求成功完成没有问题。
但是,当使用我从 AcquireTokenAsync 获得的令牌发出相同的 Web 请求时,我收到 404 错误并抛出异常。
1) 能否推荐一些好的工具来分析HTTP请求(这样我就可以比较差异并找出问题所在)。 Visual Studio 调试器很有用,但我看不到全貌,这混淆了这里可能存在的问题。
2) 你能帮我确定为什么一个成功而一个失败吗?两个token好像都获取成功了,不知道是什么问题
所以我弄清楚了这里的根本原因是什么。
在我们的身份验证场景中,我们有多个产品在生态系统中使用 azure AD SSO。由于 'OnAuthorizationCodeReceived' 仅在登录时调用,而不是在已保存有效登录 cookie 时调用,因此令牌缓存不会填充授权代码。所以在这种情况下,这种情况下的 Microsoft 代码示例是完全错误的。发出身份验证质询不会导致调用 'OnAuthorizationCodeReceived',因为您已经持有有效的登录令牌。
因此,虽然它 小 丑陋,但修复非常简单。强制注销,以便可以填充令牌缓存。
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 的 'Authentication' 面板中打开 Azure AD 身份验证。在我切换它之前,我们遇到了一些无限登录循环问题。
编辑:
因此,在这种情况下强制注销确实不适合我。但是,我遇到了这个问题:
而我们能做的就是按照答案,调用 AcquireTokenByAuthorizationCodeAsync(...),并确保使用 4 参数方法重载,其中最后一个参数是“https://graph.windows.net/”
现在,只要我们将授权代码存储在某个地方(在我的例子中存储在数据库中 table)。我们应该能够获取给定用户的授权代码,并在 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;
}
}
}
所以我有一个调用图形的应用程序 API。
请参阅以下代码段:
调用 try (AquireTokenSilent) 时,Web 请求成功完成没有问题。
但是,当使用我从 AcquireTokenAsync 获得的令牌发出相同的 Web 请求时,我收到 404 错误并抛出异常。
1) 能否推荐一些好的工具来分析HTTP请求(这样我就可以比较差异并找出问题所在)。 Visual Studio 调试器很有用,但我看不到全貌,这混淆了这里可能存在的问题。
2) 你能帮我确定为什么一个成功而一个失败吗?两个token好像都获取成功了,不知道是什么问题
所以我弄清楚了这里的根本原因是什么。
在我们的身份验证场景中,我们有多个产品在生态系统中使用 azure AD SSO。由于 'OnAuthorizationCodeReceived' 仅在登录时调用,而不是在已保存有效登录 cookie 时调用,因此令牌缓存不会填充授权代码。所以在这种情况下,这种情况下的 Microsoft 代码示例是完全错误的。发出身份验证质询不会导致调用 'OnAuthorizationCodeReceived',因为您已经持有有效的登录令牌。
因此,虽然它 小 丑陋,但修复非常简单。强制注销,以便可以填充令牌缓存。
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 的 'Authentication' 面板中打开 Azure AD 身份验证。在我切换它之前,我们遇到了一些无限登录循环问题。
编辑: 因此,在这种情况下强制注销确实不适合我。但是,我遇到了这个问题:
而我们能做的就是按照答案,调用 AcquireTokenByAuthorizationCodeAsync(...),并确保使用 4 参数方法重载,其中最后一个参数是“https://graph.windows.net/”
现在,只要我们将授权代码存储在某个地方(在我的例子中存储在数据库中 table)。我们应该能够获取给定用户的授权代码,并在 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;
}
}
}