【问题标题】:How to fix "Invalid Signature" API error when submitting a token request in OpenID flow?在 OpenID 流中提交令牌请求时如何修复“无效签名”API 错误?
【发布时间】:2019-09-27 00:08:25
【问题描述】:

我正在为我的应用程序设置 OpenID 流,并希望使用 Microsoft Active Directory 测试私钥 JWT 客户端证书身份验证。也就是说,在请求 id 和访问令牌时,我想使用证书而不是客户端机密来验证我的应用程序。但是,在发出令牌请求时,我收到以下错误:

{
   "error":"invalid_client",
   "error_description":"AADSTS700027: Client assertion contains an invalid signature. [Reason - The key was not found., Please visit 'https://developer.microsoft.com/en-us/graph/graph-explorer' and query for 'https://graph.microsoft.com/beta/applications/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' to see configured keys]\r\nTrace ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r\nCorrelation ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r\nTimestamp: 2019-09-26 22:24:19Z",
   "error_codes":[
      700027
   ],
   "timestamp":"2019-09-26 22:24:19Z",
   "trace_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
   "correlation_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
   "error_uri":"https://login.microsoftonline.com/error?code=700027"
}

我正在使用以下命令生成私钥和证书:

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes

我已将 cert.pem 上传到我在 Azure 门户中的应用注册。

在我的应用程序中,我使用 Nimbus JOSE + JWT 库来构建 JWT,并使用 Nimbus OAuth 2.0 SDK with OpenID Connect extensions 来管理 OpenID 流。以下是每个包的 Javadoc 页面:

通过检查密钥和证书是否包含 -----BEGIN PRIVATE KEY----------BEGIN CERTIFICATE----- 标头和相应的页脚,我已验证密钥和证书采用 PEM 格式。

根据错误,我访问了 https://developer.microsoft.com/en-us/graph/graph-explorer ,在左侧登录,然后使用给定的未编辑 url 发送查询。这样做给了我错误:

{
"error": {
    "code": "Request_ResourceNotFound",
    "message": "Resource 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' does not exist or one of its queried reference-property objects are not present.",
    "innerError": {
        "request-id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "date": "2019-09-26T23:47:37"
    }
}

我当前的实现如下所示。

        val privateKeyString = File(keyFilePath).readText()
        val certificateString = File(certFilePath).readText()
        val certObject = JWK.parseFromPEMEncodedX509Cert(certificateString)
        val privateKeyJWK = JWK.parseFromPEMEncodedObjects(privateKeyString)
        val privateKey = RSAKey.parse(privateKeyJWK.toJSONObject())
        val privateKeyJWT = PrivateKeyJWT(
                ClientID(configuration.clientId), // clientId retrieved from the app reg on the azure portal
                providerMetadata.tokenEndpointURI, // login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/oauth2/token
                JWSAlgorithm.RS256,
                privateKey.toRSAPrivateKey(),
                certObject.keyID,
                null)

        val tokenReq = TokenRequest(
                providerMetadata.tokenEndpointURI,
                privateKeyJWT,
                AuthorizationCodeGrant(authCode, // authCode received from previous step of the OpenID flow
                        URI(configuration.redirectURI)) // the application's login page. This has been registered in
                                                        // the app reg on the azure portal.
        )

        val tokenHTTPResponse: HTTPResponse? = tokenReq.toHTTPRequest().send()
        val tokenResponse = OIDCTokenResponse.parse(tokenHTTPResponse) // response fails with the described error

这里有几个步骤可能出错,但我无法缩小范围:

  • 我的密钥生成可能是错误的。也许我使用的密钥和证书不是预期的格式?
  • 我使用 Nimbus 库对密钥的解析可能是错误的。在请求期间单步执行代码并检查数据对象似乎表明它正在解析文件中的所有组件。它是否正确解析了这些组件尚不清楚。
  • 我的私钥 JWT 的构造可能存在缺陷。
  • 令牌请求的构造可能存在缺陷。
  • 我在 Azure 门户上注册应用程序的配置可能有误。

任何有关如何缩小范围或解决此问题的指示将不胜感激!

【问题讨论】:

    标签: oauth-2.0 active-directory openid nimbus-jose-jwt


    【解决方案1】:

    为什么这不起作用的简单答案是 Azure Active Directory 不支持私钥 JWT 身份验证。编写的代码有效,但仅适用于支持私钥 JWT 身份验证的服务。

    【讨论】:

    • 根据发布的服务器元数据它应该:login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/v2.0/… ``` "token_endpoint_auth_methods_supported":["client_secret_post","private_key_jwt","client_secret_basic"] ```
    • @VladimirDzhuvinov 该死的......我不确定我做错了什么。重要的是,当我使用 Okta 提供程序对其进行测试时,上面的代码 sn-p 和方法是有效的。
    【解决方案2】:

    有一种更简单的方法可以从 Nimbus JOSE+JWT 库生成 JWK:

    https://connect2id.com/products/nimbus-jose-jwt/examples/jwk-generation#rsa

    您的 OAuth 2.0 客户端是否已在令牌端点注册 private_key_jwt 身份验证?

    【讨论】:

    • 如何为private_key_jwt注册客户端?我将证书上传到我在活动目录门户中Certificates & Secrets 部分下的应用程序列表中。我没有通过谷歌搜索有关注册的任何信息。
    • std 方式,通过客户端 reg 端点不需要证书,只需要通过 jwks_uri 或内联传递一个 JWK 集,如 jwks:connect2id.com/products/server/docs/guides/…
    猜你喜欢
    • 1970-01-01
    • 2011-04-25
    • 2017-03-28
    • 2011-10-25
    • 2018-07-22
    • 1970-01-01
    • 1970-01-01
    • 2020-06-21
    • 2017-07-16
    相关资源
    最近更新 更多