Skip to content
This repository was archived by the owner on Apr 10, 2025. It is now read-only.

Commit b38b06f

Browse files
authored
Header parameters implementation (#22)
1 parent 939b904 commit b38b06f

File tree

3 files changed

+112
-1
lines changed

3 files changed

+112
-1
lines changed

GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.fasterxml.jackson.core.type.TypeReference;
1717
import com.fasterxml.jackson.databind.ObjectMapper;
1818
import com.genexus.JWT.claims.Claim;
19+
import com.genexus.JWT.claims.HeaderParameters;
1920
import com.genexus.JWT.claims.PrivateClaims;
2021
import com.genexus.JWT.claims.PublicClaims;
2122
import com.genexus.JWT.claims.RegisteredClaim;
@@ -52,6 +53,10 @@ public String doCreate(String algorithm, PrivateClaims privateClaims, JWTOptions
5253
return "";
5354
}
5455
Builder tokenBuilder = JWT.create();
56+
if (!options.getHeaderParameters().isEmpty()) {
57+
HeaderParameters parameters = options.getHeaderParameters();
58+
tokenBuilder.withHeader(parameters.getMap());
59+
}
5560
tokenBuilder = doBuildPayload(tokenBuilder, privateClaims, options);
5661
if (this.hasError()) {
5762
return "";
@@ -103,7 +108,8 @@ public boolean doVerify(String token, String expectedAlgorithm, PrivateClaims pr
103108
this.error.setError("JW005", e.getMessage());
104109
return false;
105110
}
106-
if (isRevoqued(decodedJWT, options) || !verifyPrivateClaims(decodedJWT, privateClaims, options)) {
111+
if (isRevoqued(decodedJWT, options) || !verifyPrivateClaims(decodedJWT, privateClaims, options)
112+
|| !verifyHeader(decodedJWT, options)) {
107113
return false;
108114
}
109115
String algorithm = decodedJWT.getAlgorithm();
@@ -386,4 +392,54 @@ private int countingPrivateClaims(Map<String, Object> map, int counter) {
386392
return counter;
387393
}
388394

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+
389445
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.genexus.JWT.claims;
2+
3+
import java.util.ArrayList;
4+
import java.util.HashMap;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
public class HeaderParameters {
9+
/*
10+
* Cannot avoid typ=JWT because of RFC 7519 https://tools.ietf.org/html/rfc7519
11+
* https://github.com/auth0/java-jwt/issues/369
12+
*/
13+
14+
private Map<String, Object> map;
15+
16+
public HeaderParameters() {
17+
map = new HashMap<String, Object>();
18+
}
19+
20+
public void setParameter(String name, String value) {
21+
map.put(name, value);
22+
}
23+
24+
public Map<String, Object> getMap() {
25+
return this.map;
26+
}
27+
28+
public List<String> getAll() {
29+
return new ArrayList<String>(map.keySet());
30+
}
31+
32+
public boolean isEmpty()
33+
{
34+
if (getAll().size() == 0)
35+
{
36+
return true;
37+
}
38+
return false;
39+
}
40+
41+
}

GeneXusJWT/src/main/java/com/genexus/commons/JWTOptions.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.bouncycastle.util.encoders.Hex;
44

5+
import com.genexus.JWT.claims.HeaderParameters;
56
import com.genexus.JWT.claims.PublicClaims;
67
import com.genexus.JWT.claims.RegisteredClaims;
78
import com.genexus.JWT.utils.RevocationList;
@@ -18,11 +19,13 @@ public class JWTOptions extends SecurityAPIObject {
1819
private RevocationList revocationList;
1920
private CertificateX509 certificate;
2021
private PrivateKeyManager privateKey;
22+
private HeaderParameters parameters;
2123

2224
public JWTOptions() {
2325
publicClaims = new PublicClaims();
2426
registeredClaims = new RegisteredClaims();
2527
revocationList = new RevocationList();
28+
parameters = new HeaderParameters();
2629
}
2730

2831
/******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/
@@ -70,6 +73,12 @@ public void addRevocationList(RevocationList revocationList) {
7073
public void deteleRevocationList() {
7174
this.revocationList = new RevocationList();
7275
}
76+
77+
public void addHeaderParameter(String name, String value)
78+
{
79+
this.parameters.setParameter(name, value);
80+
}
81+
7382

7483
/******** EXTERNAL OBJECT PUBLIC METHODS - END ********/
7584

@@ -113,4 +122,9 @@ public CertificateX509 getCertificate() {
113122
public PrivateKeyManager getPrivateKey() {
114123
return this.privateKey;
115124
}
125+
126+
public HeaderParameters getHeaderParameters()
127+
{
128+
return this.parameters;
129+
}
116130
}

0 commit comments

Comments
 (0)