如何使用ADAL JS发出的隐式授予令牌从Web API访问Graph API

问题描述:

我有一个用Java内置的Web API,它将数据库信息返回给SPA.在传递响应之前,我需要使用AAD Graph API检查用户的组信息.现在,Web API接受请求并读取用户的令牌(eyJ ...).

I have a Web API built in Java that returns database information to an SPA. I need to check the user's group information using AAD Graph API before delivering the response. Right now the Web API accepts the request and reads the user's token (eyJ...).

应用程序准备好代表用户向Graph API发送请求的下一步是什么?

What are the next steps for the application to be ready to send a request to Graph API on behalf of the user?

我尝试使用用户的令牌发送带有 Authorization:Bearer ey ... 标头的请求,但收到 Authentication_MissingOrMalformed 错误.我也尝试过对应用清单进行各种修改,并在没有运气的情况下委派了权限.

I have tried sending the request with the Authorization: Bearer ey... header using the user's token but receive a Authentication_MissingOrMalformed error. I have also tried various edits to the app manifest and delegated permissions with no luck.

您的API收到的访问令牌仅用于 您的API.您需要代表当前用户获取Azure AD Graph API的 new 访问令牌.

The access token that your API received is intended only for your API. What you need is to obtain a new access token, on behalf of the current user, for the Azure AD Graph API.

幸运的是,这恰恰是代表流量的意思.来自 Azure AD的身份验证方案:

Fortunately, this is exactly what the on-behalf-of flow is for. From Authentication Scenarios for Azure AD:

使用OAuth 2.0代表草稿规范委派的用户身份

Delegated User Identity with OAuth 2.0 On-Behalf-Of Draft Specification

下面讨论的流程假定用户已经在另一个应用程序(例如本机应用程序)上进行了身份验证,并且其用户身份已用于获取对第一层Web API的访问令牌.

The flow discussed below assumes that a user has been authenticated on another application (such as a native application), and their user identity has been used to acquire an access token to the first-tier web API.

  1. 本机应用程序将访问令牌发送到第一层Web API.
  2. 第一层Web API将请求发送到Azure AD的令牌终结点,提供其客户端ID和凭据以及用户的访问令牌.另外,该请求还带有一个on_behalf_of参数发送,该参数指示Web API正在请求新令牌来代表原始用户调用下游Web API.
  3. Azure AD验证第一层Web API有权访问第二层Web API并验证请求,然后将JWT访问令牌和JWT刷新令牌返回到第一层Web API.
  4. 通过HTTPS,第一层Web API然后通过在请求的Authorization标头中附加令牌字符串来调用第二层Web API.只要访问令牌和刷新令牌有效,第一层Web API便可以继续调用第二层Web API.
  1. The native application sends the access token to the first-tier web API.
  2. The first-tier web API sends a request to Azure AD’s token endpoint, providing its client ID and credentials, as well as the user’s access token. In addition, the request is sent with an on_behalf_of parameter that indicates the web API is requesting new tokens to call a downstream web API on behalf of the original user.
  3. Azure AD verifies that the first-tier web API has permissions to access the second-tier web API and validates the request, returning a JWT access token and a JWT refresh token to the first-tier web API.
  4. Over HTTPS, the first-tier web API then calls the second-tier web API by appending the token string in the Authorization header in the request. The first-tier web API can continue to call the second-tier web API as long as the access token and refresh tokens are valid.

请确保将您的API配置为请求Azure AD Graph API的正确权限集.

Be sure to configure your API to request the right set of permissions for the Azure AD Graph API.

编辑:如果您自己构建令牌请求,则您的API会向Azure AD发出的代表当前用户获取Graph API的新令牌的请求将是POST.反对:

Edit: If you are constructing the token request yourself, the request that your API would make to Azure AD to get a new token to the Graph API on behalf of the current user would be a POST against:

https://login.microsoftonline.com/{tenant-id}/oauth2/token

体内带有以下参数(出于可读性考虑,未经编码,实际上,这些参数实际上是application/x-www-form-urlencoded):

With the following parameters in the body (un-encoded, for readability, in reality these would be application/x-www-form-urlencoded, of course):

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&
requested_token_use=on_behalf_of&
assertion={access-token}&
client_id={api-client-id}&
client_secret={api-client-secret}&
resource=https://graph.windows.net&
scope=openid

其中{tenant-id}是目录标识符(域名或Guid值),{access-token}是SPA提供给API的访问令牌(您要交换的是Graph API的访问令牌), {api-client-id}是您的API的客户端ID,{api-client-secret}是API的秘密密码凭据.

Where {tenant-id} is the directory identifier (domain name or Guid value), {access-token} is the access token that your SPA provided to your API (the one you're exchanging for an access token to the Graph API), {api-client-id} is the client ID for your API, and {api-client-secret} is the API's secret password credential.

(注意,为简单起见,此示例使用密码凭据(client_secret)来对API进行身份验证,尽管它很可能会改用由客户端证书签名的断言.)

(Note, for simplicity, this example uses password credentials (client_secret) to authenticate the API, though it could very well be using instead an assertion signed by a client certificate.)