英文:
How to verify JWT signed by keycloak using java
问题
我有一个由Keycloak生成的JWT,采用RS256算法,类似于以下内容:
示例:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.YSFl77w-H2BIt9O-NPZ2f3G-Bf-DfKk9fMn2a4Kz64z0bTzzeA3tFAixXsqYeNBYWXWYJ83GQ2-SR1GfXnuTItBBGtb6NnwNchInZkUOVf7Ng7RvIv7GtBooByOv1aXzgKyH4P-M04lKKuZ_LwDm9Cjp9ENb7ylVKbPvRr-6DLlRvjQ
我需要解码并验证这个令牌,使用Keycloak的证书。
我可以通过API访问Keycloak的证书:
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"
}
]
}
我可以在https://jwt.io/上验证这个JWT,如果我将x5c部分放在----CERTIFICATE-----标签中。
-----BEGIN CERTIFICATE-----
MIICnTCCAYUCBgFzh2ZkQzANBgkqhkiG9w0BAQ50F/bO9PpWzJglQkU3q8CAwEAATANBgkqhkiG9w01faO/9ZzyiLMLsorUKzYPNAxc7Q9rLE0J2MCWfapx3/E4yyNjISuB1HpS5iF44OEhGHJlw7JQeogcZat0enB8yyXtP/cgBhCnrWwfugX8rHsWfHakBGdsoazR9w==
-----END CERTIFICATE-----
如何在Java中验证相同的内容?
我尝试了一些方法,但失败了。
英文:
I have JWT generated by keyCloack, RS256 something like this
sample:
eyJhbGciOwia2lkIiA6ICJtSG1lajZEc09GaV9MejdSMjhzWjdMWkxBRXVzIn0.eyBzA2MzQvOTcwNjM1L1NNUyIsIi83Ni83NS9TTVMiXSwicHJYW1lIjoidGVzdDEwNUB1c2VyLmNvbSIsInVzZXJOYW1lIjoidGVzdDEwNUB1c2VyLmNvbSIsInVzZXJJZCI6IjU4NDM2NmQ4LWU5NDItNGJhNy04OGVlLWMyZTBlODhmZmY5ZCIsImVtYWlsIjoidGVzdDEwNUB1c2VyLmNvbSJ9.4TgC1MLyUl1P36oD6FafBCh0peEaCBmkyLheVjnlBu8uePl9xgEN6wdeWe
I need to decode and validate this token using keycloack certificate.
i can reach the keycloack certificate over api.
https://xxx.xxx.com.tr/auth/realms/myrealm/protocol/openid-connect/certs
in the response, I have x5c field.
{
"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"
}
]
}
I can validate this jwt over https://jwt.io/ if I put the x5c part within ----CERTIFICATE----- tag
-----BEGIN CERTIFICATE-----
MIICnTCCAYUCBgFzh2ZkQzANBgkqhkiG9w0BAQ50F/bO9PpWzJglQkU3q8CAwEAATANBgkqhkiG9w01faO/9ZzyiLMLsorUKzYPNAxc7Q9rLE0J2MCWfapx3/E4yyNjISuB1HpS5iF44OEhGHJlw7JQeogcZat0enB8yyXtP/cgBhCnrWwfugX8rHsWfHakBGdsoazR9w==
-----END CERTIFICATE-----
how can I verify same thing in Java?
I tried couple of things but it failed.
答案1
得分: 3
我找到了方法。
首先,我们需要登录到 Keycloak 控制台,您可以找到与 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 publicKey = kf.generatePublic(keySpec);
我们已经有了公钥,现在需要验证它。
Jws<Claims> jwt = null;
try {
jwt = Jwts.parserBuilder()
.setSigningKey(publicKey)
.build()
.parseClaimsJws(token);
} catch (Exception e) {
// 如果出现错误,这意味着令牌无效。
}
英文:
I found the way.
First, we need to login keycloack console, you can reach the public key related with realm.
now you have publickey from keycloak and JWT from user.
you need to import related libraries first.
<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>
after that here is the logic.
String token = "ghfghfdhdhdfhdfghdhdfhdfhdfhhdf";
String rsaPublicKey = "awdasdsadaefafafaef5df65d4f";
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(rsaPublicKey));
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey = kf.generatePublic(keySpec);
we have publickey, we need to verify it
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
得分: 1
我认为你可以使用jose4j库来实现这个功能。
HttpsJwks httpsJkws = new HttpsJwks("https://xxx.xxx.com.tr/auth/realms/myrealm/protocol/openid-connect/certs");
HttpsJwksVerificationKeyResolver httpsJwksKeyResolver = new HttpsJwksVerificationKeyResolver(httpsJkws);
// 使用JwtConsumerBuilder构建适当的JwtConsumer,它将用于验证和处理JWT。
// 但在这种情况下,将其提供给HttpsJwksVerificationKeyResolver实例,而不是明确设置验证密钥。
jwtConsumer = new JwtConsumerBuilder()
// ... JwtConsumerBuilder的其他设置 ...
.setVerificationKeyResolver(httpsJwksKeyResolver)
// ...
.build();
英文:
I think you can use jose4j library for that.
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();
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论