无法以静默方式获取令牌 - Microsoft Graph API以获取用户的Outlook组

时间:2016-03-18 10:00:55

标签: c# api azure outlook microsoft-graph

我正在尝试访问Microsoft Graph API以获取用户的Outlook组。

以下是检索访问令牌的代码:

$needle="bob";
$output=array();
foreach($array as $k=>$v)
{
   if(stristr($k,$needle) || stristr($v,$needle))
   $output[$k]=$v;
}
print_r($output);

该方法使用设置助手,如下所示:

    public static async Task<string> GetGraphAccessTokenAsync()
    {
        string AzureAdGraphResourceURL = "https://graph.microsoft.com/";
        string signedInUserUniqueName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
        var userObjectId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
        var clientCredential = new ClientCredential(SettingsHelper.ClientId, SettingsHelper.AppKey);
        var userIdentifier = new UserIdentifier(userObjectId, UserIdentifierType.UniqueId);

        AuthenticationContext authContext = new AuthenticationContext(
            SettingsHelper.Authority, new ADALTokenCache(signedInUserUniqueName));

        var result = await authContext.AcquireTokenSilentAsync(AzureAdGraphResourceURL, clientCredential, userIdentifier);
        return result.AccessToken;
    }

这是我得到的错误: 无法以静默方式获取令牌。调用方法AcquireToken

异常详细信息:

    public class SettingsHelper
{
    private static string _clientId = ConfigurationManager.AppSettings["ida:ClientID"];
    private static string _appKey = ConfigurationManager.AppSettings["ida:Password"];

    private static string _tenantId = ConfigurationManager.AppSettings["ida:TenantID"];
    private static string _authorizationUri = "https://login.windows.net";
    private static string _authority = "https://login.windows.net/{0}/";

    private static string _graphResourceId = "https://graph.windows.net";

    public static string ClientId
    {
        get
        {
            return _clientId;
        }
    }

    public static string AppKey
    {
        get
        {
            return _appKey;
        }
    }

    public static string TenantId
    {
        get
        {
            return _tenantId;
        }
    }

    public static string AuthorizationUri
    {
        get
        {
            return _authorizationUri;
        }
    }

    public static string Authority
    {
        get
        {
            return String.Format(_authority, _tenantId);
        }
    }

    public static string AADGraphResourceId
    {
        get
        {
            return _graphResourceId;
        }
    }    
}

错误发生在此行:

    Microsoft.IdentityModel.Clients.ActiveDirectory.AdalSilentTokenAcquisitionException : Failed to acquire token silently. Call method AcquireToken

我已经检查过以确保UserIdentifier与缓存中的值匹配,但它仍然似乎拒绝令牌。我可能会出错的任何想法?

1 个答案:

答案 0 :(得分:3)

首先,确保使用Microsoft图形端点(实际上您使用的是Active Directory端点)

    private static readonly string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
    private static readonly string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
    private static readonly string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
    private static readonly string tenantId = ConfigurationManager.AppSettings["ida:TenantId"];
    private static readonly string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];

    private static readonly string graphResourceId = "https://graph.microsoft.com";
    private static readonly Uri graphEndpointId = new Uri("https://graph.microsoft.com/v1.0/");

在进行无声通话之前,您必须通过检索代码进行经典通话。我假设你在MVC应用程序中。 这是我的Startup.Auth.cs代码:

    public void ConfigureAuth(IAppBuilder app)
    {
        ApplicationDbContext db = new ApplicationDbContext();

        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = AuthenticationHelper.ClientId,
                Authority = AuthenticationHelper.AadInstance + AuthenticationHelper.TenantId,
                PostLogoutRedirectUri = AuthenticationHelper.PostLogoutRedirectUri,

                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                   AuthorizationCodeReceived =async (context) => 
                   {
                       var code = context.Code;
                       string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;

                       try
                       {
                           var result = await AuthenticationHelper.GetAccessTokenByCodeAsync(signedInUserID, code);

                       }
                       catch (Exception ex)
                       {
                           Debug.WriteLine(ex.Message);
                           //throw;
                       }


                   }
                }
            });
    }

以下是我在AuthenticationHelper类中使用的代码:

    public async static Task<AuthenticationResult> GetAccessTokenByCodeAsync(string signedInUserID, string code)
    {
            ClientCredential credential = new ClientCredential(clientId, appKey);
            AuthenticationContext authContext = new AuthenticationContext(AadInstance + TenantId, new ADALTokenCache(signedInUserID));
            AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(
            code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);

            return result;

    }

然后,每次我需要向图表发出请求时,这是我用来获取令牌的代码:

    public async static Task<string> GetTokenForApplicationAsync()
    {
        string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
        string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;

        // get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
        ClientCredential clientcred = new ClientCredential(clientId, appKey);
        // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
        AuthenticationContext authenticationContext = new AuthenticationContext(AadInstance + TenantId, new ADALTokenCache(signedInUserID));
        AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenSilentAsync(GraphResourceId, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
        return authenticationResult.AccessToken;
    }

其他要注意的事项:确保您的租户是您的租户的指导。出于某种原因,有时,如果您使用租户名称,adal会产生影响,并可能引发此类错误。