在使用客户端证书的 AcquireTokenAsync 调用期间会发生什么?

Jef*_*emi 3 azure-active-directory

在 Azure AD 中,当我们进行诸如此类的调用时,AuthenticationContext.AcquireTokenAsync(resource, new ClientAssertionCertificate(_clientId, _cert))不清楚究竟发生了什么。

如果有的话,证书的哪一部分会被交换?

是否有挑战/响应发生?

客户端是否需要私钥作为其中的一部分?

Phi*_*ret 7

您可以通过两种方式找到问题的答案。一种方法是查看GitHub 上.NET源代码的 Microsoft Active Directory 身份验证库 (ADAL) ,因为这是开源的。另一个(我们将在这里做)是查看AcquireTokenAsync(String,?ClientAssertion)生成的网络请求,并从那里向后工作。

使用Fiddler(或任何其他流量分析器),我们可以看到类似以下内容(为了可读性而格式化):

POST https://login.microsoftonline.com/{tenant-id}/oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&resource=https%3A%2F%2Fgraph.windows.net
&client_id={app-id}
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGciOiJSUzI1N...VE8wHSf-HZvGQ
Run Code Online (Sandbox Code Playgroud)

分解它:

  • grant_type=client_credentials告诉我们这是一个使用OAuth 2.0 客户端凭据授予流程的令牌请求。
  • resource=https%3A%2F%2Fgraph.windows.net给出客户端请求访问令牌的资源的 URI。在本例中,它用于 Azure AD Graph API。
  • client_id={app-id}客户端标识符。在 Azure AD 中,这是已注册应用程序的应用程序 ID。
  • 的存在client_assertion_typeclient_assertion指示该客户端使用 断言来验证:
    • client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer说正在使用的客户端断言是一个签名的JSON Web 令牌(JWT)。
    • client_assertion=eyJhbGciOiJSUzI1N...VE8wHSf-HZvGQ是上述签名的 JWT 令牌。授权服务器(例如 Azure AD)将验证内容,并检查令牌是否确实由为相关客户端授权的证书签名。

所以,ADAL 的作用是:

  1. 使用一组关于客户端(您的应用程序)的声明构建令牌
  2. 使用您证书的私钥生成这些声明的加密签名
  3. 将其捆绑成一个签名的 JWT
  4. 向权威机构发出适当格式的令牌请求

在 期间AcquireTokenAsync,仅提供证书的指纹(它包含在 JWT 标头中以帮助授权服务器查找相应的公钥)。JWT 的签名证明客户端拥有私钥。但是, AcquireTokenAsync(String,?ClientAssertion)成功使用之前,客户端所有者(即您)需要已向 Azure AD 提供证书的公钥。

这里没有发生质询/响应。令牌是在客户端发起的单个请求中获得的。

有关更多详细信息,您可以查看这一切实施的标准:

(注意 ADAL 有一个缓存。只有当 ADAL 在令牌缓存中找不到有效的访问令牌时,我上面描述的一切才会发生。您可以使用AuthenticationContext.TokenCache.Clear()清除缓存进行实验。)