Skip to content

Commit 8b4dff4

Browse files
committed
fromJWT to use getJWTVerifyKeys of KeyJar
1 parent 457c7e9 commit 8b4dff4

3 files changed

Lines changed: 97 additions & 76 deletions

File tree

src/main/java/org/oidc/msg/AbstractMessage.java

Lines changed: 75 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,23 @@ public String toJson() throws JsonProcessingException, InvalidClaimException {
187187
return jsonMsg;
188188
}
189189

190+
/**
191+
* Constructs message from JWT. If JWT has no kid defined, allows to try with any otherwise
192+
* matching key in the bundle. Allows extending the keyjar by JKU.
193+
*
194+
* @param jwt
195+
* the jwt String representation of a message
196+
* @param keyJar
197+
* KeyJar having a key for verifying the signature. If null, signature is not verified.
198+
* @param keyOwner
199+
* For whom the key belongs to.
200+
* @throws IOException
201+
* thrown if message parameters do not match the message requirements.
202+
*/
203+
public void fromJwt(String jwt, KeyJar keyJar, String keyOwner) throws IOException {
204+
fromJwt(jwt, keyJar, keyOwner, null, true, true);
205+
}
206+
190207
/**
191208
* Constructs message from JWT.
192209
*
@@ -196,11 +213,20 @@ public String toJson() throws JsonProcessingException, InvalidClaimException {
196213
* KeyJar having a key for verifying the signature. If null, signature is not verified.
197214
* @param keyOwner
198215
* For whom the key belongs to.
216+
* @param noKidIssuers
217+
* If jwt is missing kid, set the list of allowed kids in keyjar to verify jwt. if
218+
* allowMissingKid is set to true, list is not used.
219+
* @param allowMissingKid
220+
* If jwt is missing kid, try any of the owners keys to verify jwt.
221+
* @param trustJKU
222+
* Whether extending keyjar by JKU is allowed or not.
199223
* @throws InvalidClaimException
200224
* thrown if message parameters do not match the message requirements.
201225
*/
202226
@SuppressWarnings("unchecked")
203-
public void fromJwt(String jwt, KeyJar keyJar, String keyOwner) throws IOException {
227+
public void fromJwt(String jwt, KeyJar keyJar, String keyOwner,
228+
Map<String, List<String>> noKidIssuers, boolean allowMissingKid, boolean trustJKU)
229+
throws IOException {
204230
String[] parts = MessageUtil.splitToken(jwt);
205231
String headerJson;
206232
String payloadJson;
@@ -230,57 +256,36 @@ public void fromJwt(String jwt, KeyJar keyJar, String keyOwner) throws IOExcepti
230256
verifier.verify(jwt);
231257
return;
232258
}
233-
234-
Map<String, String> args = new HashMap<String, String>();
235-
args.put("alg", alg);
236-
if (header.get("kid") != null && !(header.get("alg") instanceof String)) {
237-
throw new JWTDecodeException("JWT header field kid has to be string");
238-
}
239-
// Get matching keys
240-
String kid = (String) header.get("kid");
241-
List<Key> keys = null;
242-
switch (alg) {
243-
case "RS256":
244-
case "RS384":
245-
case "RS512":
246-
keys = keyJar.getVerifyKey(KeyType.RSA.name(), keyOwner, kid, args);
247-
break;
248-
case "ES256":
249-
case "ES384":
250-
case "ES512":
251-
keys = keyJar.getVerifyKey(KeyType.EC.name(), keyOwner, kid, args);
252-
break;
253-
default:
254-
break;
255-
}
259+
List<java.security.Key> keys = keyJar.getJWTVerifyKeys(jwt, keyOwner, noKidIssuers,
260+
allowMissingKid, trustJKU);
256261
if (keys == null || keys.size() == 0) {
257262
throw new JWTDecodeException("Not able to locate keys to verify JWT");
258263
}
259264
// We try each located key
260265
try {
261-
for (Key key : keys) {
266+
for (java.security.Key key : keys) {
262267
Algorithm algorithm = null;
263268
switch (alg) {
264-
case "RS256":
265-
algorithm = Algorithm.RSA256((RSAPublicKey) key.getKey(false), null);
266-
break;
267-
case "RS384":
268-
algorithm = Algorithm.RSA384((RSAPublicKey) key.getKey(false), null);
269-
break;
270-
case "RS512":
271-
algorithm = Algorithm.RSA512((RSAPublicKey) key.getKey(false), null);
272-
break;
273-
case "ES256":
274-
algorithm = Algorithm.ECDSA256((ECPublicKey) key.getKey(false), null);
275-
break;
276-
case "ES384":
277-
algorithm = Algorithm.ECDSA384((ECPublicKey) key.getKey(false), null);
278-
break;
279-
case "ES512":
280-
algorithm = Algorithm.ECDSA512((ECPublicKey) key.getKey(false), null);
281-
break;
282-
default:
283-
break;
269+
case "RS256":
270+
algorithm = Algorithm.RSA256((RSAPublicKey) key, null);
271+
break;
272+
case "RS384":
273+
algorithm = Algorithm.RSA384((RSAPublicKey) key, null);
274+
break;
275+
case "RS512":
276+
algorithm = Algorithm.RSA512((RSAPublicKey) key, null);
277+
break;
278+
case "ES256":
279+
algorithm = Algorithm.ECDSA256((ECPublicKey) key, null);
280+
break;
281+
case "ES384":
282+
algorithm = Algorithm.ECDSA384((ECPublicKey) key, null);
283+
break;
284+
case "ES512":
285+
algorithm = Algorithm.ECDSA512((ECPublicKey) key, null);
286+
break;
287+
default:
288+
break;
284289
}
285290
if (algorithm == null) {
286291
throw new JWTDecodeException("Not able to initialize algorithm to verify JWT");
@@ -294,7 +299,7 @@ public void fromJwt(String jwt, KeyJar keyJar, String keyOwner) throws IOExcepti
294299
continue;
295300
}
296301
}
297-
} catch (IllegalArgumentException | ValueError e) {
302+
} catch (IllegalArgumentException e) {
298303
throw new JWTDecodeException("Key handling exception");
299304
}
300305
throw new JWTDecodeException("Not able to verify JWT with any of the keys provided");
@@ -322,30 +327,30 @@ public String toJwt(Key key, String alg) {
322327
Algorithm algorithm = null;
323328
try {
324329
switch (alg) {
325-
case "none":
326-
algorithm = Algorithm.none();
327-
break;
328-
case "RS256":
329-
algorithm = Algorithm.RSA256(null, (RSAPrivateKey) key.getKey(true));
330-
break;
331-
case "RS384":
332-
algorithm = Algorithm.RSA384(null, (RSAPrivateKey) key.getKey(true));
333-
break;
334-
case "RS512":
335-
algorithm = Algorithm.RSA512(null, (RSAPrivateKey) key.getKey(true));
336-
break;
337-
case "ES256":
338-
algorithm = Algorithm.ECDSA256(null, (ECPrivateKey) key.getKey(true));
339-
break;
340-
case "ES384":
341-
algorithm = Algorithm.ECDSA384(null, (ECPrivateKey) key.getKey(true));
342-
break;
343-
case "ES512":
344-
algorithm = Algorithm.ECDSA512(null, (ECPrivateKey) key.getKey(true));
345-
break;
346-
default:
347-
break;
348-
// TODO: HMAC algorithms
330+
case "none":
331+
algorithm = Algorithm.none();
332+
break;
333+
case "RS256":
334+
algorithm = Algorithm.RSA256(null, (RSAPrivateKey) key.getKey(true));
335+
break;
336+
case "RS384":
337+
algorithm = Algorithm.RSA384(null, (RSAPrivateKey) key.getKey(true));
338+
break;
339+
case "RS512":
340+
algorithm = Algorithm.RSA512(null, (RSAPrivateKey) key.getKey(true));
341+
break;
342+
case "ES256":
343+
algorithm = Algorithm.ECDSA256(null, (ECPrivateKey) key.getKey(true));
344+
break;
345+
case "ES384":
346+
algorithm = Algorithm.ECDSA384(null, (ECPrivateKey) key.getKey(true));
347+
break;
348+
case "ES512":
349+
algorithm = Algorithm.ECDSA512(null, (ECPrivateKey) key.getKey(true));
350+
break;
351+
default:
352+
break;
353+
// TODO: HMAC algorithms, are getting client secret also from key jar?
349354
}
350355
} catch (IllegalArgumentException | ValueError e) {
351356
// TODO: This is not Decoding exception, replace it.

src/main/java/org/oidc/msg/Message.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import java.io.IOException;
2525
import java.net.MalformedURLException;
26+
import java.util.List;
2627
import java.util.Map;
2728

2829
/**
@@ -75,13 +76,27 @@ void fromUrlEncoded(String input)
7576
throws MalformedURLException, IOException, InvalidClaimException;
7677

7778
/**
78-
*
79-
* @param input
79+
* Constructs message from JWT.
80+
*
81+
* @param jwt
8082
* the jwt String representation of a message
81-
* @param KeyJar
82-
* that might contain the necessary key
83+
* @param keyJar
84+
* KeyJar having a key for verifying the signature. If null, signature is not verified.
85+
* @param keyOwner
86+
* For whom the key belongs to.
87+
* @param noKidIssuers
88+
* If jwt is missing kid, set the list of allowed kids in keyjar to verify jwt. if
89+
* allowMissingKid is set to true, list is not used.
90+
* @param allowMissingKid
91+
* If jwt is missing kid, try any of the owners keys to verify jwt.
92+
* @param trustJKU
93+
* Whether extending keyjat by JKU is allowed or not.
94+
* @throws InvalidClaimException
95+
* thrown if message parameters do not match the message requirements.
8396
*/
84-
void fromJwt(String input, KeyJar keyJar, String keyOwner) throws IOException;
97+
@SuppressWarnings("unchecked")
98+
public void fromJwt(String jwt, KeyJar keyJar, String keyOwner,
99+
Map<String, List<String>> noKidIssuers, boolean allowMissingKid, boolean trustJKU) throws IOException;
85100

86101
/**
87102
*

src/test/java/org/oidc/msg/BaseMessageTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ public abstract class BaseMessageTest<T extends AbstractMessage> {
4646

4747
private static final String PRIVATE_KEY_FILE = "src/test/resources/rsa-private.pem";
4848
private static final String PUBLIC_KEY_FILE = "src/test/resources/rsa-public.pem";
49-
protected String keyOwner = "https://issuer.example.com";
49+
//TODO: return keyOwner to https://issuer.example.com once edmund explains how parameter is used in getJWTVerifyKeys
50+
protected String keyOwner = "";//"https://issuer.example.com";
5051
protected KeyJar keyJarOfPrivateKeys = null;
5152
protected KeyJar keyJarOfPublicKeys = null;
5253
protected String signedJwt = null;

0 commit comments

Comments
 (0)