获取 Microsoft Graph API 的有效访问令牌

Posted

技术标签:

【中文标题】获取 Microsoft Graph API 的有效访问令牌【英文标题】:Obtaining a valid access token for Microsoft Graph API 【发布时间】:2017-08-31 00:29:52 【问题描述】:

我正在开发一个使用 Azure ADAL 库对用户进行身份验证的 ASP.NET MVC5 Web 应用程序,它工作正常,但是,当我手动向图形发送请求时,例如:GET https://graph.microsoft.com/v1.0/me 或 GET https://graph.microsoft.com/v1.0/groups?$ filter=from/displayName eq 'whatever'。

我已尝试在 Azure 中更新应用注册以添加所需的 Graph 权限,并且我还尝试创建新的应用注册,无论我做什么,我的请求都会始终响应 401 Unauthorized,我还缺少什么吗?

编辑:邮递员的示例响应


  "error": 
    "code": "InvalidAuthenticationToken",
    "message": "Access token validation failure.",
    "innerError": 
      "request-id": "a142576b-acce-4e59-8a8d-adede61aaf59",
      "date": "2017-04-05T13:27:36"
    
  

编辑:C# 请求示例

public async Task<GroupGraph> GetGroupIdByDisplayName(string displayName)

    var accessToken = await authenticationService.GetTokenUserOnly();
    GroupGraph groupGraphResponse = null;
    using (var client = new HttpClient())
    
        using (var request = new HttpRequestMessage(HttpMethod.Get, $"https://graph.microsoft.com/v1.0/groups?$filter=from/displayName eq 'displayName'"))
            
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
                using (var response = client.SendAsync(request).Result)
                
                    if (response.IsSuccessStatusCode)
                    
                        using (var content = response.Content)
                        
                            var result = await content.ReadAsStringAsync();
                            groupGraphResponse = JsonConvert.DeserializeObject<GroupGraph>(result);
                        
                    
                
            
        
        return groupGraphResponse;
    

编辑:我获得令牌的方式

public async Task<string> GetTokenUserOnly()
    
        string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
        string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").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 TableTokenCache(signedInUserID));
        //AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenSilentAsync(graphResourceID, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
        AuthenticationResult authenticationResult = authenticationContext.AcquireToken(graphResourceID, clientcred);
        return authenticationResult.AccessToken;
    

【问题讨论】:

您能描述一下when I manually send requests to graph 的意思吗?您是否通过 Postman 或 Fiddler 等工具发送请求?您是否在请求中包含 Authorization 标头? 是的,我的请求中包含了授权标头,我尝试使用 Postman 和 C# 来发送我的请求。 请更新您的问题并包含代码。您还应该看到有关 401 错误的详细信息。请将它们也包括在您的问题中。 【参考方案1】:

您不能使用 ADAL 来获取 graph.microsoft.com 的令牌。 ADAL 用于图形。windows.net。

为了获取图形库 (graph.windows.com) 的令牌,请查看 Nuget 包 Microsoft.Graph。微软也有一些关于如何使用 Graph 提取用户信息的documentation。

但请注意,同时使用图形库和 ADAL 库可能会导致一些奇怪的副作用,例如凭据缓存被清除。

【讨论】:

这不准确。您绝对可以使用 ADAL 获取 Microsoft Graph (https://graph.microsoft.com) 的令牌。您只需要确保您使用的是 V1 应用程序并遵循 V1 协议/端点。【参考方案2】:

您似乎正在使用客户端凭据授予流程来获取图形 api 的访问令牌(graphResourceIDhttps://graph.microsoft.com ?):

  AuthenticationResult authenticationResult = authenticationContext.AcquireToken(graphResourceID, clientcred);

因此您需要在 azure 广告门户中授予应用权限:

对于“访问令牌验证失败”错误,您可以使用http://jwt.calebb.net/等在线工具来解码您的访问令牌,检查访问令牌的受众或生命周期。

【讨论】:

那些权限已经在app注册中了,是graphResourceID是graph.microsoft.com【参考方案3】:

要获取 Microsoft Graph API 的有效令牌,您可以使用 Azure.Identity

要使用TokenCredential 的任何实现,我们需要构建自己的IAuthenticationProvider

public class TokenCredentialAuthenticationProvider : IAuthenticationProvider

    private readonly TokenCredential _tokenCredential;

    public TokenCredentialAuthenticationProvider(TokenCredential tokenCredential)
    
        _tokenCredential = tokenCredential;
    
    public async Task AuthenticateRequestAsync(HttpRequestMessage request)
    
        var accessToken = await _tokenCredential.GetTokenAsync(new TokenRequestContext(new[]  "https://graph.microsoft.com" ), CancellationToken.None);
        request.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken.Token);
    

现在我们可以使用 AzureCliCredential 来获取访问令牌。

打开 Powershell 并输入 az login 以使用您的 Azure AD 帐户登录。

在 Azure 中,您还可以使用 Managed Identity 获取基于 Azure 资源的令牌,例如Azure 应用服务。这里需要使用ManagedIdentityToken

用法:

var client = new GraphServiceClient(new TokenCredentialAuthenticationProvider(new AzureCliCredential()));
var user = await client.Me.Request().GetAsync();

【讨论】:

以上是关于获取 Microsoft Graph API 的有效访问令牌的主要内容,如果未能解决你的问题,请参考以下文章

通过 Microsoft Graph API 发送自适应卡片 - 获取提交操作时出错

使用 Microsoft Graph API 获取修改后的系列事件发生

如何使用 Microsoft Graph API 获取当前站点的 siteId?

Microsoft Graph API calendarView 是不是仅限于一个月?如何获取所有事件?

Microsoft Graph API - 列出用户登录的所有权限/范围

Microsoft Graph API应用程序注册问题