1
1
package com .avast .grpc .jwt .keycloak .server ;
2
2
3
3
import com .avast .grpc .jwt .server .JwtTokenParser ;
4
- import com .fasterxml .jackson .databind .ObjectMapper ;
5
4
import com .google .common .base .Strings ;
6
- import java .net .URL ;
7
- import java .security .PublicKey ;
8
5
import java .util .concurrent .CompletableFuture ;
9
6
import java .util .concurrent .CompletionException ;
10
7
import org .keycloak .TokenVerifier ;
11
8
import org .keycloak .common .VerificationException ;
12
9
import org .keycloak .constants .ServiceUrlConstants ;
13
- import org .keycloak .jose .jwk .JSONWebKeySet ;
14
- import org .keycloak .jose .jwk .JWK ;
15
- import org .keycloak .jose .jwk .JWKParser ;
16
10
import org .keycloak .representations .AccessToken ;
17
11
import org .keycloak .util .TokenUtil ;
18
12
19
13
public class KeycloakJwtTokenParser implements JwtTokenParser <AccessToken > {
20
14
21
- protected final PublicKey publicKey ;
15
+ protected final KeycloakPublicKeyProvider publicKeyProvider ;
22
16
protected final TokenVerifier .Predicate <AccessToken >[] checks ;
23
17
protected String expectedAudience ;
24
18
protected String expectedIssuedFor ;
25
19
26
- protected KeycloakJwtTokenParser (String serverUrl , String realm , PublicKey publicKey ) {
27
- this .publicKey = publicKey ;
20
+ public KeycloakJwtTokenParser (
21
+ String serverUrl , String realm , KeycloakPublicKeyProvider publicKeyProvider ) {
22
+ this .publicKeyProvider = publicKeyProvider ;
28
23
String realmUrl =
29
24
serverUrl + ServiceUrlConstants .REALM_INFO_PATH .replace ("{realm-name}" , realm );
30
25
this .checks =
@@ -38,7 +33,14 @@ protected KeycloakJwtTokenParser(String serverUrl, String realm, PublicKey publi
38
33
39
34
@ Override
40
35
public CompletableFuture <AccessToken > parseToValid (String jwtToken ) {
41
- TokenVerifier <AccessToken > verifier = createTokenVerifier (jwtToken );
36
+ TokenVerifier <AccessToken > verifier ;
37
+ try {
38
+ verifier = createTokenVerifier (jwtToken );
39
+ } catch (VerificationException e ) {
40
+ CompletableFuture <AccessToken > r = new CompletableFuture <>();
41
+ r .completeExceptionally (e );
42
+ return r ;
43
+ }
42
44
return CompletableFuture .supplyAsync (
43
45
() -> {
44
46
try {
@@ -49,15 +51,17 @@ public CompletableFuture<AccessToken> parseToValid(String jwtToken) {
49
51
});
50
52
}
51
53
52
- protected TokenVerifier <AccessToken > createTokenVerifier (String jwtToken ) {
54
+ protected TokenVerifier <AccessToken > createTokenVerifier (String jwtToken )
55
+ throws VerificationException {
53
56
TokenVerifier <AccessToken > verifier =
54
- TokenVerifier .create (jwtToken , AccessToken .class ).withChecks (checks ). publicKey ( publicKey ) ;
57
+ TokenVerifier .create (jwtToken , AccessToken .class ).withChecks (checks );
55
58
if (!Strings .isNullOrEmpty (expectedAudience )) {
56
59
verifier = verifier .audience (expectedAudience );
57
60
}
58
61
if (!Strings .isNullOrEmpty (expectedIssuedFor )) {
59
62
verifier = verifier .issuedFor (expectedIssuedFor );
60
63
}
64
+ verifier .publicKey (publicKeyProvider .get (verifier .getHeader ().getKeyId ()));
61
65
return verifier ;
62
66
}
63
67
@@ -70,20 +74,4 @@ public KeycloakJwtTokenParser withExpectedIssuedFor(String expectedIssuedFor) {
70
74
this .expectedIssuedFor = expectedIssuedFor ;
71
75
return this ;
72
76
}
73
-
74
- public static KeycloakJwtTokenParser create (String serverUrl , String realm ) {
75
- try {
76
- ObjectMapper om = new ObjectMapper ();
77
- String jwksUrl = serverUrl + ServiceUrlConstants .JWKS_URL .replace ("{realm-name}" , realm );
78
- JSONWebKeySet jwks = om .readValue (new URL (jwksUrl ).openStream (), JSONWebKeySet .class );
79
- if (jwks .getKeys ().length == 0 ) {
80
- throw new RuntimeException ("No keys found" );
81
- }
82
- JWK jwk = jwks .getKeys ()[0 ];
83
- PublicKey publicKey = JWKParser .create (jwk ).toPublicKey ();
84
- return new KeycloakJwtTokenParser (serverUrl , realm , publicKey );
85
- } catch (Exception e ) {
86
- throw new RuntimeException ("Exception when obtaining public key from " + serverUrl , e );
87
- }
88
- }
89
77
}
0 commit comments