【问题标题】:signing a JWT with a .pfx file使用 .pfx 文件签署 JWT
【发布时间】:2020-06-29 17:20:22
【问题描述】:

我需要使用 their certificate flow 从 Microsoft 获取访问令牌。

我认为它应该与this 帖子中解释的内容非常相似,但我只从在 Azure 帐户中设置租户应用程序的人那里获得了一个 .pfx 文件。 如果我尝试按照这些步骤操作,系统会要求我“输入导入密码”——我不知道。

我可以做些什么来使用这个 .pfx 文件签署 JWT 令牌?

编辑:我正在使用带有 Microsoft 身份验证库 (MSAL) 的 Java。

【问题讨论】:

  • 1/2) 您需要知道密码才能使用 PFX (PKCS#12) 文件,因为内容已加密。您的目标是使用 OAuth 机密客户端断言。 Microsoft 提供的库使这变得非常简单,否则您将需要 base64 证书哈希并使用私钥签署 JWT。使用语言、运行时的详细信息以及是否要使用库或手工编写的代码来编辑您的问题。对于 c#,本文展示了最简单的方法以及如何手工编写代码:docs.microsoft.com/en-us/azure/active-directory/develop/…
  • 2/2) 不要忘记先将公钥 (.cer) 上传到 Azure AD。
  • 有没有办法在java中用pfx对jwt进行签名?你发现了吗?

标签: azure jwt certificate pfx


【解决方案1】:

你可以尝试做这样的事情-

第 1 步:加载证书 

object CertUtil {
  private val DIGEST_ALGORITHM = "SHA-1"
  private val keyStore = KeyStore.getInstance("PKCS12")

  def loadCertificate(certLocation: String, pwdLocation: String): Certificate = {
    keyStore.load(new FileInputStream(new File(certLocation)), readPassword(pwdLocation).toCharArray)
    keyStore.getCertificate(keyStore.aliases().nextElement())
  }

第 2 步:创建 client_assertion

Client Assertion 是使用您证书的私钥签名的 jwt,由 AAD 服务器用于在颁发令牌之前对您的请求执行身份检查。

def createJWTToken(aadURL: String, clientId: String, scope: String, key: Key, certThumbPrint: String): String =
  Jwts.builder()
    .claim(Claims.AUDIENCE, aadURL)
    .claim(Claims.ISSUER, clientId)
    .claim(Claims.SUBJECT, clientId)
    .claim(Claims.ID, UUID.randomUUID.toString)
    .claim(Claims.EXPIRATION, NOW + ONE_HOUR)
    .claim(Claims.NOT_BEFORE, NOW)
    .setHeaderParam(X5THUMBPRINT, certThumbPrint)
    .signWith(key)
    .compact()

第 3 步:使用客户端断言令牌创建 Post Payload

包含要以 url 编码形式提交给 AAD 服务的 clientId、Scope、GrantType、Client Assertion 的 Payload。

def getPayload(request: AADRequest): String = {
  val token = JWTCreator
    .createJWTToken(
      aadURL(request.tenentId),
      request.clientId,
      getScope(request.appId),
      CertUtil.getPrivateKey,
      CertUtil.getThumbPrint
    )
  Map(
    (CLIENT_ID, request.clientId),
    (SCOPE, getScope(request.appId)),
    (GRANT_TYPE, GRANT_TYPE_VAL),
    (CLIENT_ASSERTION_TYPE, CLIENT_ASSERTION_TYPE_VAL),
    (CLIENT_ASSERTION, token))
    .map(_.productIterator.mkString("="))
    .mkString("&")
}

第 4 步:调用 Azure AD Post API

private def aadURL(tenentId: String) = s"${BASE_URL}${tenentId}${PATH}"

private def getScope(appId: String) = s"api://${appId}/.default"
def getAADToken(request: AADRequest): Future[String] = {
  CertUtil.loadCertificate(request.certPath, request.pwdPath)
  doPost(toPostRequest(aadURL(request.tenentId),
getHttpEntity(request)))
    .flatMap(response => Unmarshal(response.entity).to[String])
    .map(s => mapper.readValue(s, classOf[AADResponse]).accessToken)
}

编辑

Maven 依赖项 -

<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.6.7.1</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.module</groupId>
      <artifactId>jackson-module-scala_${scala.version.major}</artifactId>
      <version>2.6.7.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.typesafe.akka/akka-actor -->
    <dependency>
      <groupId>com.typesafe.akka</groupId>
      <artifactId>akka-actor_2.12</artifactId>
      <version>2.6.12</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.typesafe.akka/akka-stream -->
    <dependency>
      <groupId>com.typesafe.akka</groupId>
      <artifactId>akka-stream_2.12</artifactId>
      <version>2.6.12</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.typesafe.akka/akka-http -->
    <dependency>
      <groupId>com.typesafe.akka</groupId>
      <artifactId>akka-http_2.12</artifactId>
      <version>10.2.3</version>
    </dependency>

    <dependency>
      <groupId>io.jsonwebtoken</groupId>
      <artifactId>jjwt-api</artifactId>
      <version>0.11.1</version>
    </dependency>
    <dependency>
      <groupId>io.jsonwebtoken</groupId>
      <artifactId>jjwt-impl</artifactId>
      <version>0.11.1</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>io.jsonwebtoken</groupId>
      <artifactId>jjwt-jackson</artifactId>
      <version>0.11.1</version>
      <scope>runtime</scope>
    </dependency>

【讨论】:

  • 您能否更新您的答案以包括所需的库和语言版本以及构建代码所需的其他详细信息?
  • 我已经更新了所需的依赖项。
猜你喜欢
  • 1970-01-01
  • 2011-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-21
  • 2020-05-17
  • 1970-01-01
相关资源
最近更新 更多