如何使用 java 验证由 keycloak 签名的 JWT
Posted
技术标签:
【中文标题】如何使用 java 验证由 keycloak 签名的 JWT【英文标题】:How to verify JWT signed by keycloak using java 【发布时间】:2020-11-26 13:17:00 【问题描述】:我有 keyCloack 生成的 JWT,类似这样的 RS256
样本:
eyJhbGciOwia2lkIiA6ICJtSG1lajZEc09GaV9MejdSMjhzWjdMWkxBRXVzIn0.eyBzA2MzQvOTcwNjM1L1NNUyIsIi83Ni83NS9TTVMiXSwicHJYW1lIjoidGVzdDEwNUB1c2VyLmNvbSIsInVzZXJOYW1lIjoidGVzdDEwNUB1c2VyLmNvbSIsInVzZXJJZCI6IjU4NDM2NmQ4LWU5NDItNGJhNy04OGVlLWMyZTBlODhmZmY5ZCIsImVtYWlsIjoidGVzdDEwNUB1c2VyLmNvbSJ9.4TgC1MLyUl1P36oD6FafBCh0peEaCBmkyLheVjnlBu8uePl9xgEN6wdeWe
我需要使用 keycloack 证书解码和验证这个令牌。
我可以通过 api 访问 keycloack 证书。
https://xxx.xxx.com.tr/auth/realms/myrealm/protocol/openid-connect/certs
在响应中,我有 x5c 字段。
"keys": [
"kid": "j6DsCpPOz1RXJhtPR28sZ7LZLAEus",
"kty": "RSA",
"alg": "RS256",
"use": "sig",
"n": "m0oTFvyLhLGIciXfndxc7uhIKE2-q9nJQKByd0FVYe8Cd4CHDpTzzcYdPWRR-1_VKQ75wqpybRt-LnnTKPNCXrPtPDRn2GFihtYyyO8VjeVtnz-iYJJAHkdp25HlMtX9l-VjnQX9s70-lbMmCVCRTerw",
"e": "AQAB",
"x5c": [
"MIICnTCCAYUCBgFzh2ZkQzANBgkqhkiG9w0BAQ50F/bO9PpWzJglQkU3q8CAwEAATANBgkqhkiG9w01faO/9ZzyiLMLsorUKzYPNAxc7Q9rLE0J2MCWfapx3/E4yyNjISuB1HpS5iF44OEhGHJlw7JQeogcZat0enB8yyXtP/cgBhCnrWwfugX8rHsWfHakBGdsoazR9w=="
],
"x5t": "YF6LE97opzsTtD-yLNx9-Lo",
"x5t#S256": "SdNCfMbCjvcq-JY3iiGAj7De9Hal_0Cck-bDFK3Ow"
]
如果我将 x5c 部分放在 ----CERTIFICATE----- 标签中,我可以通过 https://jwt.io/ 验证这个 jwt
-----BEGIN CERTIFICATE-----
MIICnTCCAYUCBgFzh2ZkQzANBgkqhkiG9w0BAQ50F/bO9PpWzJglQkU3q8CAwEAATANBgkqhkiG9w01faO/9ZzyiLMLsorUKzYPNAxc7Q9rLE0J2MCWfapx3/E4yyNjISuB1HpS5iF44OEhGHJlw7JQeogcZat0enB8yyXtP/cgBhCnrWwfugX8rHsWfHakBGdsoazR9w==
-----END CERTIFICATE-----
如何在 Java 中验证相同的内容?
我尝试了几件事,但都失败了。
【问题讨论】:
这能回答你的问题吗? Verifying JWT Signature using public key endpoint @jps 不是我在下面添加了解决方案 如果您正在向 keycloak 编写插件,使用 AppAuthManager 可以帮助您验证令牌。这不是您正在寻找的,但可能会对某人有所帮助。 【参考方案1】:我找到了路。
首先,我们需要登录keycloack控制台,你可以得到与realm相关的公钥。
现在您拥有来自 keycloak 的公钥和来自用户的 JWT。
需要先导入相关库。
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
接下来就是逻辑了。
String token = "ghfghfdhdhdfhdfghdhdfhdfhdfhhdf";
String rsaPublicKey = "awdasdsadaefafafaef5df65d4f";
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(rsaPublicKey));
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey = kf.generatePublic(keySpec);
我们有公钥,我们需要验证它
Jws<Claims> jwt = null;
try
jwt = Jwts.parserBuilder()
.setSigningKey(publicKey)
.build()
.parseClaimsJws(token);
catch (Exception e)
// if you get error, that means token is invalid.
【讨论】:
【参考方案2】:我认为您可以为此使用 jose4j 库。
HttpsJwks httpsJkws = new HttpsJwks("https://xxx.xxx.com.tr/auth/realms/myrealm/protocol/openid-connect/certs");
HttpsJwksVerificationKeyResolver httpsJwksKeyResolver = new HttpsJwksVerificationKeyResolver(httpsJkws);
// Use JwtConsumerBuilder to construct an appropriate JwtConsumer, which will
// be used to validate and process the JWT. But, in this case, provide it with
// the HttpsJwksVerificationKeyResolver instance rather than setting the
// verification key explicitly.
jwtConsumer = new JwtConsumerBuilder()
// ... other set up of the JwtConsumerBuilder ...
.setVerificationKeyResolver(httpsJwksKeyResolver)
// ...
.build();
【讨论】:
虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review @Carsten Løvbo Andersen 你是绝对正确的。我编辑了我的答案。以上是关于如何使用 java 验证由 keycloak 签名的 JWT的主要内容,如果未能解决你的问题,请参考以下文章
http://jwt.io 如何检索 keycloak 签名密钥?
验证openssl c ++中的签名,该签名由JAVA DSA签名?
我应该明确验证 Keycloak 令牌还是由 Keycloak 适配器完成?