调用AcquireTokenAsync后,AAD Graph API返回404,但调用AcquireTokenSilentAsync后,则不返回404

时间:2018-08-22 00:24:56

标签: asp.net oauth azure-active-directory azure-ad-graph-api

所以我有一个调用图形API的应用程序。

请参见以下代码段: enter image description here

调用try(AquireTokenSilent)时,Web请求成功完成,没有问题。

但是,当使用从AcquireTokenAsync获得的令牌进行相同的Web请求时,出现了404错误和抛出异常。

1)您能否推荐一些好的工具来分析HTTP请求(以便我可以比较差异并确定问题)。 Visual Studio调试器很有用,但是我看不到整个图片,这使这里的问题变得难以理解。

2)您能帮我确定为什么一个成功和一个失败的原因吗?这两个令牌似乎都已成功获取,所以我不确定问题出在哪里。

1 个答案:

答案 0 :(得分:0)

所以我已经弄清楚了根本原因是什么。

在我们的身份验证方案中,我们有多种产品在生态系统中使用天蓝色的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();
        }

现在,因为我们正在Controllers外部使用此代码,并且我们调用await,所以HttpContext将为null。 HttpContext中发生了一些严重的伏都教,但我离题了。我们可以使用这种小变通方法来挂起上下文:

        var context = HttpContext.Current;
        var sessionState = context.Session;

编辑:在将应用程序部署到azure应用程序服务时遇到了另一个问题。您要确保在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;
                    }

                }
            }