Azure Active Directory Graph API - 登录用户的访问令牌

Azure Active Directory Graph API - access token for signed in user

Azure Active Directory Graph Api 允许您对登录用户执行操作。

https://msdn.microsoft.com/en-us/library/azure/ad/graph/api/signed-in-user-operations

我不知道如何代表登录用户获取 Graph API 的访问令牌。

我可以为我的 Web 应用程序获取访问令牌,但这并不代表特定用户:

var authContext = new AuthenticationContext(authorityString);
var result = await authContext.AcquireTokenAsync
             (
                "https://graph.windows.net",
                 clientCredential  // Application ID, application secret
             );
string accessToken = result.Token;

此外,当用户登录时,我会得到一个授权码(通过 AuthorizationCodeReceived 通知)。我可以将此授权码转换为访问令牌。这可能是用户的访问令牌,但 Graph Api 无法识别它。 (想想看,我不知道这个access token有什么用...)

var authContext = new AuthenticationContext(authorityString);
var result = await authContext.AcquireTokenByAuthorizationCodeAsync
             (
                  authorizationCode,
                  redirectUri, // eg http://localhost:56950/
                  clientCredential // Application ID, application secret
             );
string accessToken = result.AccessToken;

使用第一个访问令牌,我可以 运行 查询我的 Active Directory 租户。例如,调用 https://graph.windows.net/thisisnotmydomain.onmicrosoft.com/users?api-version=1.6 给了我一个用户列表。

但是如果尝试 URL:https://graph.windows.net/me?api-version=1.6,我得到这个结果:

   {
     "odata.error": {
                       "code": "Request_ResourceNotFound",
                      "message": {
                                   "lang": "en",
                                   "value": "Resource not found for the segment 'me'."
                                  }
                    }
  }

这是有道理的,因为我从未指定用户。如果我使用通过 AcquireTokenByAuthorizactionCodeAsync 获得的访问令牌,我会收到一条错误消息 "Access Token missing or malformed." 显然,这不是图 API 访问令牌。

如何获取适用于已登录用户的 Graph API 的访问令牌?

您在那里所做的是客户端凭据授予流程。应用程序使用它来访问 APIs,但不代表用户,而是应用程序本身。因此,如果您的应用有权在没有用户上下文的情况下从 API 读取数据,这就是您要使用的内容。

但是,要在用户上下文中进行调用,您需要做一些不同的事情。

如果这是一个 Web 应用程序,您可能会使用授权代码授予流程,在该流程中,用户的浏览器将被重定向到 Azure AD。在同意您的应用程序后,他们将使用授权代码转发回您的应用程序。然后,您可以使用该代码以及您的客户端 ID 和密码将此代码交换为访问令牌。这是执行此操作的示例应用程序:https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-openidconnect, focus especially here: https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-openidconnect/blob/master/TodoListWebApp/App_Start/Startup.Auth.cs.

如果这是一个原生应用程序,你将不得不弹出一个浏览器来进行身份验证。这是由 ADAL 自动执行的,因此您无需执行太多操作。这是一个示例 UWP 应用程序:https://github.com/Azure-Samples/active-directory-dotnet-windows-store. Focus especially here: https://github.com/Azure-Samples/active-directory-dotnet-windows-store/blob/master/TodoListClient/MainPage.xaml.cs#L108. There is also a sample WPF app here: https://github.com/Azure-Samples/active-directory-dotnet-native-desktop。 WPF 应用程序所做的也可以应用于控制台应用程序、winforms 应用程序等。

您可以在此处找到所有示例:https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-code-samples

如果您有更多问题,请随时在评论中提问:)

P.S。另一种选择是密码授予流程,在该流程中,您将用户名、密码、客户端 ID 和机密发送到 Azure AD 以获取访问令牌。这种方法会带来很多问题,所以我不推荐它。如果您可以使用在浏览器中向用户显示登录屏幕的那些 window,请使用它们。


第二次调用授权码的问题是没有指定资源URI。像这样调用解决了问题:

var result = await authContext.AcquireTokenByAuthorizationCodeAsync
         (
              authorizationCode,
              redirectUri, // eg http://localhost:56950/
              clientCredential, // Application ID, application secret
              "https://graph.windows.net/"
         );