|
16 | 16 | import com.fasterxml.jackson.core.type.TypeReference; |
17 | 17 | import com.fasterxml.jackson.databind.ObjectMapper; |
18 | 18 | import com.genexus.JWT.claims.Claim; |
| 19 | +import com.genexus.JWT.claims.HeaderParameters; |
19 | 20 | import com.genexus.JWT.claims.PrivateClaims; |
20 | 21 | import com.genexus.JWT.claims.PublicClaims; |
21 | 22 | import com.genexus.JWT.claims.RegisteredClaim; |
@@ -52,6 +53,10 @@ public String doCreate(String algorithm, PrivateClaims privateClaims, JWTOptions |
52 | 53 | return ""; |
53 | 54 | } |
54 | 55 | Builder tokenBuilder = JWT.create(); |
| 56 | + if (!options.getHeaderParameters().isEmpty()) { |
| 57 | + HeaderParameters parameters = options.getHeaderParameters(); |
| 58 | + tokenBuilder.withHeader(parameters.getMap()); |
| 59 | + } |
55 | 60 | tokenBuilder = doBuildPayload(tokenBuilder, privateClaims, options); |
56 | 61 | if (this.hasError()) { |
57 | 62 | return ""; |
@@ -103,7 +108,8 @@ public boolean doVerify(String token, String expectedAlgorithm, PrivateClaims pr |
103 | 108 | this.error.setError("JW005", e.getMessage()); |
104 | 109 | return false; |
105 | 110 | } |
106 | | - if (isRevoqued(decodedJWT, options) || !verifyPrivateClaims(decodedJWT, privateClaims, options)) { |
| 111 | + if (isRevoqued(decodedJWT, options) || !verifyPrivateClaims(decodedJWT, privateClaims, options) |
| 112 | + || !verifyHeader(decodedJWT, options)) { |
107 | 113 | return false; |
108 | 114 | } |
109 | 115 | String algorithm = decodedJWT.getAlgorithm(); |
@@ -386,4 +392,54 @@ private int countingPrivateClaims(Map<String, Object> map, int counter) { |
386 | 392 | return counter; |
387 | 393 | } |
388 | 394 |
|
| 395 | + private boolean verifyHeader(DecodedJWT decodedJWT, JWTOptions options) { |
| 396 | + HeaderParameters parameters = options.getHeaderParameters(); |
| 397 | + if (parameters.isEmpty()) { |
| 398 | + return true; |
| 399 | + } |
| 400 | + |
| 401 | + List<String> allParms = parameters.getAll(); |
| 402 | + if (allParms.size() + 2 != getHeaderClaimsNumber(decodedJWT)) { |
| 403 | + return false; |
| 404 | + } |
| 405 | + Map<String, Object> map = parameters.getMap(); |
| 406 | + for (String s : allParms) { |
| 407 | + |
| 408 | + if (decodedJWT.getHeaderClaim(s) == null) { |
| 409 | + return false; |
| 410 | + } |
| 411 | + com.auth0.jwt.interfaces.Claim c = decodedJWT.getHeaderClaim(s); |
| 412 | + String claimValue = null; |
| 413 | + try { |
| 414 | + claimValue = c.asString().trim(); |
| 415 | + } catch (NullPointerException e) { |
| 416 | + return false; |
| 417 | + } |
| 418 | + String optionsValue = ((String) map.get(s)).trim(); |
| 419 | + if (!SecurityUtils.compareStrings(claimValue, optionsValue)) { |
| 420 | + return false; |
| 421 | + } |
| 422 | + } |
| 423 | + return true; |
| 424 | + |
| 425 | + } |
| 426 | + |
| 427 | + private int getHeaderClaimsNumber(DecodedJWT decodedJWT) { |
| 428 | + String base64Part = decodedJWT.getHeader(); |
| 429 | + byte[] base64Bytes = Base64.decodeBase64(base64Part); |
| 430 | + EncodingUtil eu = new EncodingUtil(); |
| 431 | + String plainTextPart = eu.getString(base64Bytes); |
| 432 | + HashMap<String, Object> map = new HashMap<String, Object>(); |
| 433 | + ObjectMapper mapper = new ObjectMapper(); |
| 434 | + |
| 435 | + try { |
| 436 | + map = mapper.readValue(plainTextPart, new TypeReference<Map<String, Object>>() { |
| 437 | + }); |
| 438 | + } catch (Exception e) { |
| 439 | + return 0; |
| 440 | + } |
| 441 | + return map.size(); |
| 442 | + |
| 443 | + } |
| 444 | + |
389 | 445 | } |
0 commit comments