パッケージを使用して、特定の keyId の公開鍵を JWK 形式で返す REST 認証サーバーを実装しましたcom.nimbusds:nimbus-jose-jwt:9.13
。コードは次のようになります。
@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 キーを返します。
{
"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;
}
}
parse
ただし、 が例外をスローするため、クライアントはキーを解析できません( Missing parameter "kty"
)。メインの JWT josn 本体にキーがJWK.parse
必要ですが、デフォルトのシリアル化ではキーがキー内に埋め込まれます。試してみると、メインのjson本体にキーが表示されます。kty
JWK
kty
requiredParams
jwk.toString()
kty
ネイティブ JWK オブジェクトのシリアル化/逆シリアル化が単純な方法で機能しないのはなぜですか? カスタム jwt 構造またはシリアライザー/デシリアライザーを実装せずにこれを修正する最良の方法は何でしょうか?
更新 1 : このコードは、戻り値の型JWK
をMap<String, Object>
orに変更String
し、クライアント側で逆シリアル化を処理する場合に機能します。ただし、パッケージがネイティブに (デ) シリアル化を行う方がよいでしょう。