java - 无法在 Java 中解析 JWK

标签 java jwt jwk nimbus-jose-jwt

我实现了一个 rest 授权服务器,它使用 com.nimbusds:nimbus-jose-jwt:9.13 以 JWK 格式返回给定 keyId 的公钥包裹。代码看起来像这样:

@RequestMapping(value = "/oauth2", produces = APPLICATION_JSON_VALUE)
public interface Rest {
...
    @GetMapping("/public-key/{keyId}")
    @Operation(summary = "Return the public key corresponding to the key id")
    JWK getPublicKey(@PathVariable String keyId);
}

public class RestController implements Rest {
.....
 public JWK getPublicKey(String keyId) {
         byte[] publicKeyBytes = ....
         RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyBytes));
         JWK jwk = new RSAKey.Builder(publicKey)
                .keyID(keyId)
                .algorithm(new Algorithm(publicKey.getAlgorithm()))
                .keyUse(KeyUse.SIGNATURE)
                .build();
         return jwk;
    }
}

此代码返回以下格式的 JWK key :

{
    "keyStore": null,
    "private": false,
    "publicExponent": {},
    "modulus": {},
    "firstPrimeFactor": null,
    "secondPrimeFactor": null,
    "firstFactorCRTExponent": null,
    "secondFactorCRTExponent": null,
    "firstCRTCoefficient": null,
    "otherPrimes": [],
    "requiredParams": {
        "e": "some-valid-exponent",
        "kty": "RSA",
        "n": "some-valid-modulus"
    },
    "privateExponent": null,
    "x509CertChain": null,
    "algorithm": {
        "name": "RSA",
        "requirement": null
    },
    "keyOperations": null,
    "keyID": "some-valid-key-id",
    "x509CertURL": null,
    "x509CertThumbprint": null,
    "x509CertSHA256Thumbprint": null,
    "parsedX509CertChain": null,
    "keyUse": {
        "value": "sig"
    },
    "keyType": {
        "value": "RSA",
        "requirement": "REQUIRED"
    }
}

在客户端(java),我尝试使用以下代码解析 jwk:

public JWK getPublicKey(String keyId) {
 String json = restTemplate.getForObject(publicUrl + "/oauth2/public-key/" + keyId, String.class);
        try {
            return JWK.parse(json);
        } catch (ParseException e) {
            log.error("Unable to parse JWK", e);
            return null;
        }
}

但是,客户端无法解析 key ,因为 parse抛出异常(Missing parameter "kty")。我看到了 JWK.parse需要 kty主 JWT josn 主体中的键,而默认序列化为 JWK嵌入 kty requiredParams 中的键 key 。当我尝试 jwk.toString() ,我确实看到了 kty在主要的 json 正文中键入。

为什么 native JWK 对象的序列化/反序列化不能以直接的方式工作?在不实现自定义 jwt 结构或序列化器/反序列化器的情况下解决此问题的最佳方法是什么?

更新 1:如果我们更改 JWK 的返回类型,此代码将起作用至 Map<String, Object>String并在客户端处理反序列化。但是,如果包本身为我们执行(反)序列化会更好。

最佳答案

答案是使用String对于那些面临这个问题的人(反)序列化。你为什么问?根据RFC ,JWK是JSON格式的字符串。同时 nimbusds:nimbus-jose-jwt定义一个 JWK 对象,任何返回有效 JWK(或 JWKSet )的 API 都可以假定它是一个字符串。

我也提出了这个issue与这个包的开发者一起,他们推荐使用 StringMap<String, Object>用于(反)序列化。

关于java - 无法在 Java 中解析 JWK,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68926941/

相关文章:

java - Android 中的 Nanohttpd

java - 当我点击运行时,eclipse 总是走错路径

java - 从命令行编译

kubernetes - Istio (1.6.2) : DENY policy in Authorization Policy does not work with Valid Token

c# - .Net Core IsAuthenticated false 即使我手动使用 HttpContext.SignInAsync

c# - 如何使用 JWK 为 ES256 alg 验证 JWT?

java - maven 和 jboss 模块

android - 如何以正确的方式将 jwt 存储在 android 应用程序中?

python - 使用 JWK/JWT 进行用户身份验证的 token 验证失败

c# - 如何在 C# 中正确使用 OpenID Connect jwks_uri 元数据?