在C#中用于在AAD中生成UserAssertion的令牌

时间:2017-06-29 14:04:35

标签: c# asp.net-mvc azure-active-directory

我们希望使用AcquireTokenAsync代表用户使用以下语法获取令牌

public static async Task<UserTokenCache> GetAccessTokens(string userUniqueId)
    {
        UserTokenCache cache = null;
        AuthenticationContext authContext = null;
        ClientCredential credential = new ClientCredential(clientId, appKey);
        AuthenticationResult powerBIResult = null;
        AuthenticationResult graphResult = null;
        bool isAdalException = false;
        try
        {
            authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userUniqueId));

            powerBIResult = await authContext.AcquireTokenSilentAsync(pbiResourceID, credential, new UserIdentifier(userUniqueId, UserIdentifierType.UniqueId));

            graphResult = await authContext.AcquireTokenSilentAsync(graphResourceId, credential, new UserIdentifier(userUniqueId, UserIdentifierType.UniqueId));

            cache = new UserTokenCache
            {
                GraphAccessToken = graphResult.AccessToken,
                PBIAccessToken = powerBIResult.AccessToken,
                PBITokenExpires = powerBIResult.ExpiresOn,
                GraphTokenExpires = graphResult.ExpiresOn
            };

        }
        catch (JsonException je)
        {
            ExceptionLogger.LogInApplicationInsight(je);
            HttpContext.Current.GetOwinContext().Authentication.Challenge(
                       new AuthenticationProperties(),
                       OpenIdConnectAuthenticationDefaults.AuthenticationType);
        }
        catch (AdalException ae)
        {
            ExceptionLogger.LogInApplicationInsight(ae);
            if (ae.ErrorCode == "failed_to_acquire_token_silently")
            {
                isAdalException = true;       
            }
            else
            {
                HttpContext.Current.GetOwinContext().Authentication.Challenge(
                           new AuthenticationProperties(),
                           OpenIdConnectAuthenticationDefaults.AuthenticationType);
            }
        }
        catch (Exception ex)
        {
            ExceptionLogger.LogInApplicationInsight(ex);
        }
        if(isAdalException)
        {
            try
            {

                string cacheValue = Convert.ToString(cacheManager.get(userUniqueId));
                string decryptedCache = CryptographyUtility.Decrypt(cacheValue);
                cache = JsonConvert.DeserializeObject<UserTokenCache>(decryptedCache);

                UserAssertion pbiAssertion = new UserAssertion(cache.PBIAccessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer", UserProperties.UserName);
                UserAssertion graphAssertion = new UserAssertion(cache.GraphAccessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer", UserProperties.UserName);

                cache = null;

                powerBIResult = await authContext.AcquireTokenAsync(pbiResourceID, credential, pbiAssertion);
                graphResult = await authContext.AcquireTokenAsync(graphResourceId, credential, graphAssertion);

                cache = new UserTokenCache
                {
                    GraphAccessToken = graphResult.AccessToken,
                    PBIAccessToken = powerBIResult.AccessToken,
                    PBITokenExpires = powerBIResult.ExpiresOn,
                    GraphTokenExpires = graphResult.ExpiresOn
                };
            } catch (Exception ex)
            {
                ExceptionLogger.LogInApplicationInsight(ex);
            }
        }
        return cache;

    }

如果我们使用cache.PBIAccessToken和cache.GraphAccessToken来计算在AcquireTokenAsync方法中使用的用户断言,则抛出TenantId不匹配的错误。在这种情况下,需要使用什么令牌来计算UserAssertion。

1 个答案:

答案 0 :(得分:0)

通常,我们通常使用AcquireTokenAsync来获取访问令牌并在用户首次登录时刷新令牌。之后,您可以静默获取令牌(调用AcquireTokenSilentAsync以获取accessToken),它将从TokenCache获取令牌或静默使用refreshToken。如果访问令牌和刷新令牌都已过期,您可能会收到AdalSilentTokenAcquisitionException(无法以静默方式获取令牌。调用方法AcquireToken)。

然后您可以捕获该异常,并调用HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/" },OpenIdConnectAuthenticationDefaults.AuthenticationType);将用户重定向到azure广告登录页面,登录后,用户使用AcquireTokenSilentAsync调用api将起作用,因为访问令牌/刷新令牌存在于缓存中,并且未过期。如果我正确理解您的要求,if(isAdalException)中的代码将毫无用处。