From f278725568d481fb135d988261309a332dce2bb7 Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Thu, 18 Jun 2020 11:03:22 -0300 Subject: [PATCH 01/10] Change version to 16.11.0 (#18) --- GeneXusCryptography/pom.xml | 2 +- GeneXusFtps/pom.xml | 2 +- GeneXusJWT/pom.xml | 2 +- GeneXusSftp/pom.xml | 2 +- GeneXusXmlSignature/pom.xml | 2 +- SecurityAPICommons/pom.xml | 2 +- pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/GeneXusCryptography/pom.xml b/GeneXusCryptography/pom.xml index f41023b..39c31f5 100644 --- a/GeneXusCryptography/pom.xml +++ b/GeneXusCryptography/pom.xml @@ -7,7 +7,7 @@ com.genexus SecurityAPIParent - 1.0.0.3 + 16.11.0 diff --git a/GeneXusFtps/pom.xml b/GeneXusFtps/pom.xml index ea2500f..eeb6dd4 100644 --- a/GeneXusFtps/pom.xml +++ b/GeneXusFtps/pom.xml @@ -8,7 +8,7 @@ com.genexus SecurityAPIParent - 1.0.0.3 + 16.11.0 diff --git a/GeneXusJWT/pom.xml b/GeneXusJWT/pom.xml index 9b29790..4671d0c 100644 --- a/GeneXusJWT/pom.xml +++ b/GeneXusJWT/pom.xml @@ -7,7 +7,7 @@ com.genexus SecurityAPIParent - 1.0.0.3 + 16.11.0 diff --git a/GeneXusSftp/pom.xml b/GeneXusSftp/pom.xml index 85e41d2..796d502 100644 --- a/GeneXusSftp/pom.xml +++ b/GeneXusSftp/pom.xml @@ -7,7 +7,7 @@ com.genexus SecurityAPIParent - 1.0.0.3 + 16.11.0 diff --git a/GeneXusXmlSignature/pom.xml b/GeneXusXmlSignature/pom.xml index 964f737..fa2dd36 100644 --- a/GeneXusXmlSignature/pom.xml +++ b/GeneXusXmlSignature/pom.xml @@ -7,7 +7,7 @@ com.genexus SecurityAPIParent - 1.0.0.3 + 16.11.0 GeneXusXmlSignature diff --git a/SecurityAPICommons/pom.xml b/SecurityAPICommons/pom.xml index cbcd196..47c4503 100644 --- a/SecurityAPICommons/pom.xml +++ b/SecurityAPICommons/pom.xml @@ -7,7 +7,7 @@ com.genexus SecurityAPIParent - 1.0.0.3 + 16.11.0 diff --git a/pom.xml b/pom.xml index 6a7c4b1..b464a99 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.genexus SecurityAPIParent - 1.0.0.3 + 16.11.0 pom GeneXusSecurityAPI (Parent) From 29bc7c7c0af5e2f6c01fde62b872df6682e5db74 Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Mon, 22 Jun 2020 16:09:40 -0300 Subject: [PATCH 02/10] Change java-jwt to version 3.10.3 (#19) --- GeneXusJWT/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GeneXusJWT/pom.xml b/GeneXusJWT/pom.xml index 4671d0c..102e9da 100644 --- a/GeneXusJWT/pom.xml +++ b/GeneXusJWT/pom.xml @@ -26,7 +26,7 @@ com.auth0 java-jwt - 3.9.0 + 3.10.3 From 939b904ee9118a5c0c9413be69e838b7c8111f52 Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Tue, 23 Jun 2020 17:19:09 -0300 Subject: [PATCH 03/10] Nested PrivateClaims implementation (#21) --- .../main/java/com/genexus/JWT/JWTCreator.java | 149 ++++++++++++++---- .../java/com/genexus/JWT/claims/Claim.java | 20 ++- .../java/com/genexus/JWT/claims/Claims.java | 5 +- .../com/genexus/JWT/claims/PrivateClaims.java | 26 ++- .../genexus/JWT/claims/RegisteredClaims.java | 8 +- 5 files changed, 165 insertions(+), 43 deletions(-) diff --git a/GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java b/GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java index a4fc6f2..513898e 100644 --- a/GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java +++ b/GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java @@ -1,5 +1,7 @@ package com.genexus.JWT; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -11,6 +13,8 @@ import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.JWTVerifier; import com.auth0.jwt.interfaces.Verification; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.genexus.JWT.claims.Claim; import com.genexus.JWT.claims.PrivateClaims; import com.genexus.JWT.claims.PublicClaims; @@ -25,17 +29,18 @@ import com.genexus.securityapicommons.keys.PrivateKeyManager; import com.genexus.securityapicommons.utils.SecurityUtils; - - public class JWTCreator extends JWTObject { + private int counter; + public JWTCreator() { super(); EncodingUtil eu = new EncodingUtil(); eu.setEncoding("UTF8"); - + this.counter = 0; + } - + /******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/ public String doCreate(String algorithm, PrivateClaims privateClaims, JWTOptions options) { if (options.hasError()) { @@ -98,7 +103,7 @@ public boolean doVerify(String token, String expectedAlgorithm, PrivateClaims pr this.error.setError("JW005", e.getMessage()); return false; } - if (isRevoqued(decodedJWT, options) || !verifyPrivateClaims(decodedJWT, privateClaims)) { + if (isRevoqued(decodedJWT, options) || !verifyPrivateClaims(decodedJWT, privateClaims, options)) { return false; } String algorithm = decodedJWT.getAlgorithm(); @@ -107,12 +112,11 @@ public boolean doVerify(String token, String expectedAlgorithm, PrivateClaims pr return false; } JWTAlgorithm expectedJWTAlgorithm = JWTAlgorithm.getJWTAlgorithm(expectedAlgorithm, this.error); - if(alg.compareTo(expectedJWTAlgorithm) != 0 || this.hasError()) - { - this.error.setError("JW008", "Expected algorithm does not match token algorithm"); - return false; - } - + if (alg.compareTo(expectedJWTAlgorithm) != 0 || this.hasError()) { + this.error.setError("JW008", "Expected algorithm does not match token algorithm"); + return false; + } + Algorithm algorithmType = null; if (JWTAlgorithm.isPrivate(alg)) { CertificateX509 cert = options.getCertificate(); @@ -150,7 +154,7 @@ public boolean doVerify(String token, String expectedAlgorithm, PrivateClaims pr error.setError("JW006", e.getMessage()); return false; } - + return true; } @@ -236,7 +240,11 @@ private Builder doBuildPayload(Builder tokenBuilder, PrivateClaims privateClaims List privateC = privateClaims.getAllClaims(); for (int i = 0; i < privateC.size(); i++) { try { - tokenBuilder.withClaim(privateC.get(i).getKey(), privateC.get(i).getValue()); + if (privateC.get(i).getNestedClaims() != null) { + tokenBuilder.withClaim(privateC.get(i).getKey(), privateC.get(i).getNestedClaims().getNestedMap()); + } else { + tokenBuilder.withClaim(privateC.get(i).getKey(), privateC.get(i).getValue()); + } } catch (Exception e) { this.error.setError("JW004", e.getMessage()); return null; @@ -275,32 +283,107 @@ private Builder doBuildPayload(Builder tokenBuilder, PrivateClaims privateClaims // ****END BUILD PAYLOAD****// return tokenBuilder; } - - private boolean verifyPrivateClaims(DecodedJWT decodedJWT, PrivateClaims privateClaims) - { - if(privateClaims == null || privateClaims.isEmpty()) - { + + private boolean verifyPrivateClaims(DecodedJWT decodedJWT, PrivateClaims privateClaims, JWTOptions options) { + RegisteredClaims registeredClaims = options.getAllRegisteredClaims(); + PublicClaims publicClaims = options.getAllPublicClaims(); + if (privateClaims == null || privateClaims.isEmpty()) { return true; } - Map map = decodedJWT.getClaims(); - - List claims = privateClaims.getAllClaims(); - for(int i= 0; i < claims.size(); i++) - { - Claim c = claims.get(i); - if(!map.containsKey(c.getKey())) - { - return false; - } - com.auth0.jwt.interfaces.Claim claim = map.get(c.getKey()); - if(!SecurityUtils.compareStrings(claim.asString().trim(), c.getValue().trim())) - { - return false; + String base64Part = decodedJWT.getPayload(); + byte[] base64Bytes = Base64.decodeBase64(base64Part); + EncodingUtil eu = new EncodingUtil(); + String plainTextPart = eu.getString(base64Bytes); + HashMap map = new HashMap(); + ObjectMapper mapper = new ObjectMapper(); + + try { + map = mapper.readValue(plainTextPart, new TypeReference>() { + }); + } catch (Exception e) { + this.error.setError("JW009", "Cannot parse JWT payload"); + return false; + } + this.counter = 0; + boolean validation = verifyNestedClaims(privateClaims.getNestedMap(), map, registeredClaims, publicClaims); + int pClaimsCount = countingPrivateClaims(privateClaims.getNestedMap(), 0); + if (validation && !(this.counter == pClaimsCount)) { + return false; + } + return validation; + } + + private boolean verifyNestedClaims(Map pclaimMap, Map map, + RegisteredClaims registeredClaims, PublicClaims publicClaims) { + List mapClaimKeyList = new ArrayList(map.keySet()); + List pClaimKeyList = new ArrayList(pclaimMap.keySet()); + if (pClaimKeyList.size() > pClaimKeyList.size()) { + return false; + } + for (String mapKey : mapClaimKeyList) { + + if (!isRegistered(mapKey, registeredClaims) && !isPublic(mapKey, publicClaims)) { + + this.counter++; + if (!pclaimMap.containsKey(mapKey)) { + return false; + } + + Object op = pclaimMap.get(mapKey); + Object ot = map.get(mapKey); + + if (op instanceof String && ot instanceof String) { + + if (!SecurityUtils.compareStrings(((String) op).trim(), ((String) ot).trim())) { + return false; + } + } else if (op instanceof HashMap && ot instanceof HashMap) { + @SuppressWarnings("unchecked") + boolean flag = verifyNestedClaims((HashMap) op, (HashMap) ot, + registeredClaims, publicClaims); + if (!flag) { + return false; + } + } else { + return false; + } } } return true; } - + private boolean isRegistered(String claimKey, RegisteredClaims registeredClaims) { + + List registeredClaimsList = registeredClaims.getAllClaims(); + for (Claim s : registeredClaimsList) { + if (SecurityUtils.compareStrings(s.getKey().trim(), claimKey.trim())) { + return true; + } + } + return false; + } + + private boolean isPublic(String claimKey, PublicClaims publicClaims) { + List publicClaimsList = publicClaims.getAllClaims(); + for (Claim s : publicClaimsList) { + if (SecurityUtils.compareStrings(s.getKey().trim(), claimKey.trim())) { + return true; + } + } + return false; + } + + @SuppressWarnings("unchecked") + private int countingPrivateClaims(Map map, int counter) { + List list = new ArrayList(map.keySet()); + for (String s : list) { + counter++; + Object obj = map.get(s); + if (obj instanceof HashMap) { + counter = countingPrivateClaims((HashMap) obj, counter); + } + } + return counter; + } } diff --git a/GeneXusJWT/src/main/java/com/genexus/JWT/claims/Claim.java b/GeneXusJWT/src/main/java/com/genexus/JWT/claims/Claim.java index 1e844d9..7d2cdc5 100644 --- a/GeneXusJWT/src/main/java/com/genexus/JWT/claims/Claim.java +++ b/GeneXusJWT/src/main/java/com/genexus/JWT/claims/Claim.java @@ -3,15 +3,27 @@ public class Claim { private String key; - private String value; + private Object value; - public Claim(String valueKey, String valueOfValue) { + public Claim(String valueKey, Object valueOfValue) { key = valueKey; value = valueOfValue; - } + } public String getValue() { - return value; + if (value instanceof String) { + return (String) value; + } else { + return null; + } + } + + public PrivateClaims getNestedClaims() { + if (value instanceof PrivateClaims) { + return (PrivateClaims) value; + } else { + return null; + } } public String getKey() { diff --git a/GeneXusJWT/src/main/java/com/genexus/JWT/claims/Claims.java b/GeneXusJWT/src/main/java/com/genexus/JWT/claims/Claims.java index bfcc10f..32f01f7 100644 --- a/GeneXusJWT/src/main/java/com/genexus/JWT/claims/Claims.java +++ b/GeneXusJWT/src/main/java/com/genexus/JWT/claims/Claims.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.List; -import com.genexus.JWT.utils.JWTUtils; import com.genexus.securityapicommons.commons.Error; import com.genexus.securityapicommons.utils.SecurityUtils; @@ -13,9 +12,9 @@ public class Claims { public Claims() { claims = new ArrayList(); - } + } - public boolean setClaim(String key, String value, Error error) { + public boolean setClaim(String key, Object value, Error error) { Claim claim = new Claim(key, value); claims.add(claim); return true; diff --git a/GeneXusJWT/src/main/java/com/genexus/JWT/claims/PrivateClaims.java b/GeneXusJWT/src/main/java/com/genexus/JWT/claims/PrivateClaims.java index 4df21d9..422fe05 100644 --- a/GeneXusJWT/src/main/java/com/genexus/JWT/claims/PrivateClaims.java +++ b/GeneXusJWT/src/main/java/com/genexus/JWT/claims/PrivateClaims.java @@ -1,6 +1,8 @@ package com.genexus.JWT.claims; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.genexus.securityapicommons.commons.Error; @@ -8,11 +10,33 @@ public final class PrivateClaims extends Claims { private List claims; + public PrivateClaims() { super(); + } - + public boolean setClaim(String key, String value) { return super.setClaim(key, value, new Error()); } + + public boolean setClaim(String key, PrivateClaims value) + { + + return super.setClaim(key, value, new Error()); + } + + public Map getNestedMap() { + HashMap result = new HashMap(); + for (Claim c : getAllClaims()) { + if (c.getValue() != null) { + result.put(c.getKey(), c.getValue()); + } else { + result.put(c.getKey(), ((PrivateClaims) c.getNestedClaims()).getNestedMap()); + } + } + + return result; + } + } diff --git a/GeneXusJWT/src/main/java/com/genexus/JWT/claims/RegisteredClaims.java b/GeneXusJWT/src/main/java/com/genexus/JWT/claims/RegisteredClaims.java index e8d990d..c98c49b 100644 --- a/GeneXusJWT/src/main/java/com/genexus/JWT/claims/RegisteredClaims.java +++ b/GeneXusJWT/src/main/java/com/genexus/JWT/claims/RegisteredClaims.java @@ -3,7 +3,6 @@ import java.util.HashMap; import java.util.List; -import com.genexus.JWT.utils.JWTUtils; import com.genexus.securityapicommons.commons.Error; import com.genexus.securityapicommons.utils.SecurityUtils; @@ -15,10 +14,15 @@ public final class RegisteredClaims extends Claims { public RegisteredClaims() { super(); customTimeValidationClaims = new HashMap(); - + } @Override + public boolean setClaim(String key, Object value, Error error) { + error.setError("RC001", "Not alllowed data type"); + return false; + } + public boolean setClaim(String key, String value, Error error) { if (RegisteredClaim.exists(key)) { return super.setClaim(key, value, error); From b38b06fe40fbe5f5be06560f5a9bb245c54923c1 Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Thu, 25 Jun 2020 14:51:32 -0300 Subject: [PATCH 04/10] Header parameters implementation (#22) --- .../main/java/com/genexus/JWT/JWTCreator.java | 58 ++++++++++++++++++- .../genexus/JWT/claims/HeaderParameters.java | 41 +++++++++++++ .../java/com/genexus/commons/JWTOptions.java | 14 +++++ 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 GeneXusJWT/src/main/java/com/genexus/JWT/claims/HeaderParameters.java diff --git a/GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java b/GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java index 513898e..de5d6aa 100644 --- a/GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java +++ b/GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.genexus.JWT.claims.Claim; +import com.genexus.JWT.claims.HeaderParameters; import com.genexus.JWT.claims.PrivateClaims; import com.genexus.JWT.claims.PublicClaims; import com.genexus.JWT.claims.RegisteredClaim; @@ -52,6 +53,10 @@ public String doCreate(String algorithm, PrivateClaims privateClaims, JWTOptions return ""; } Builder tokenBuilder = JWT.create(); + if (!options.getHeaderParameters().isEmpty()) { + HeaderParameters parameters = options.getHeaderParameters(); + tokenBuilder.withHeader(parameters.getMap()); + } tokenBuilder = doBuildPayload(tokenBuilder, privateClaims, options); if (this.hasError()) { return ""; @@ -103,7 +108,8 @@ public boolean doVerify(String token, String expectedAlgorithm, PrivateClaims pr this.error.setError("JW005", e.getMessage()); return false; } - if (isRevoqued(decodedJWT, options) || !verifyPrivateClaims(decodedJWT, privateClaims, options)) { + if (isRevoqued(decodedJWT, options) || !verifyPrivateClaims(decodedJWT, privateClaims, options) + || !verifyHeader(decodedJWT, options)) { return false; } String algorithm = decodedJWT.getAlgorithm(); @@ -386,4 +392,54 @@ private int countingPrivateClaims(Map map, int counter) { return counter; } + private boolean verifyHeader(DecodedJWT decodedJWT, JWTOptions options) { + HeaderParameters parameters = options.getHeaderParameters(); + if (parameters.isEmpty()) { + return true; + } + + List allParms = parameters.getAll(); + if (allParms.size() + 2 != getHeaderClaimsNumber(decodedJWT)) { + return false; + } + Map map = parameters.getMap(); + for (String s : allParms) { + + if (decodedJWT.getHeaderClaim(s) == null) { + return false; + } + com.auth0.jwt.interfaces.Claim c = decodedJWT.getHeaderClaim(s); + String claimValue = null; + try { + claimValue = c.asString().trim(); + } catch (NullPointerException e) { + return false; + } + String optionsValue = ((String) map.get(s)).trim(); + if (!SecurityUtils.compareStrings(claimValue, optionsValue)) { + return false; + } + } + return true; + + } + + private int getHeaderClaimsNumber(DecodedJWT decodedJWT) { + String base64Part = decodedJWT.getHeader(); + byte[] base64Bytes = Base64.decodeBase64(base64Part); + EncodingUtil eu = new EncodingUtil(); + String plainTextPart = eu.getString(base64Bytes); + HashMap map = new HashMap(); + ObjectMapper mapper = new ObjectMapper(); + + try { + map = mapper.readValue(plainTextPart, new TypeReference>() { + }); + } catch (Exception e) { + return 0; + } + return map.size(); + + } + } diff --git a/GeneXusJWT/src/main/java/com/genexus/JWT/claims/HeaderParameters.java b/GeneXusJWT/src/main/java/com/genexus/JWT/claims/HeaderParameters.java new file mode 100644 index 0000000..3a1d288 --- /dev/null +++ b/GeneXusJWT/src/main/java/com/genexus/JWT/claims/HeaderParameters.java @@ -0,0 +1,41 @@ +package com.genexus.JWT.claims; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class HeaderParameters { + /* + * Cannot avoid typ=JWT because of RFC 7519 https://tools.ietf.org/html/rfc7519 + * https://github.com/auth0/java-jwt/issues/369 + */ + + private Map map; + + public HeaderParameters() { + map = new HashMap(); + } + + public void setParameter(String name, String value) { + map.put(name, value); + } + + public Map getMap() { + return this.map; + } + + public List getAll() { + return new ArrayList(map.keySet()); + } + + public boolean isEmpty() + { + if (getAll().size() == 0) + { + return true; + } + return false; + } + +} diff --git a/GeneXusJWT/src/main/java/com/genexus/commons/JWTOptions.java b/GeneXusJWT/src/main/java/com/genexus/commons/JWTOptions.java index 4d485a6..56cd107 100644 --- a/GeneXusJWT/src/main/java/com/genexus/commons/JWTOptions.java +++ b/GeneXusJWT/src/main/java/com/genexus/commons/JWTOptions.java @@ -2,6 +2,7 @@ import org.bouncycastle.util.encoders.Hex; +import com.genexus.JWT.claims.HeaderParameters; import com.genexus.JWT.claims.PublicClaims; import com.genexus.JWT.claims.RegisteredClaims; import com.genexus.JWT.utils.RevocationList; @@ -18,11 +19,13 @@ public class JWTOptions extends SecurityAPIObject { private RevocationList revocationList; private CertificateX509 certificate; private PrivateKeyManager privateKey; + private HeaderParameters parameters; public JWTOptions() { publicClaims = new PublicClaims(); registeredClaims = new RegisteredClaims(); revocationList = new RevocationList(); + parameters = new HeaderParameters(); } /******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/ @@ -70,6 +73,12 @@ public void addRevocationList(RevocationList revocationList) { public void deteleRevocationList() { this.revocationList = new RevocationList(); } + + public void addHeaderParameter(String name, String value) + { + this.parameters.setParameter(name, value); + } + /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ @@ -113,4 +122,9 @@ public CertificateX509 getCertificate() { public PrivateKeyManager getPrivateKey() { return this.privateKey; } + + public HeaderParameters getHeaderParameters() + { + return this.parameters; + } } From a7b42cf12f32b74e297f94bc3653c865c9a9f9d2 Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Tue, 30 Jun 2020 16:46:09 -0300 Subject: [PATCH 05/10] Change jackson libraries version to 2.11.0 (#23) --- GeneXusJWT/pom.xml | 6 +++--- GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/GeneXusJWT/pom.xml b/GeneXusJWT/pom.xml index 102e9da..361c5f3 100644 --- a/GeneXusJWT/pom.xml +++ b/GeneXusJWT/pom.xml @@ -32,19 +32,19 @@ com.fasterxml.jackson.core jackson-databind - 2.9.10.4 + 2.11.0 com.fasterxml.jackson.core jackson-annotations - 2.9.9 + 2.11.0 com.fasterxml.jackson.core jackson-core - 2.9.9 + 2.11.0 diff --git a/GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java b/GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java index de5d6aa..416af06 100644 --- a/GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java +++ b/GeneXusJWT/src/main/java/com/genexus/JWT/JWTCreator.java @@ -304,7 +304,7 @@ private boolean verifyPrivateClaims(DecodedJWT decodedJWT, PrivateClaims private ObjectMapper mapper = new ObjectMapper(); try { - map = mapper.readValue(plainTextPart, new TypeReference>() { + map = (HashMap) mapper.readValue(plainTextPart, new TypeReference>() { }); } catch (Exception e) { this.error.setError("JW009", "Cannot parse JWT payload"); @@ -433,7 +433,7 @@ private int getHeaderClaimsNumber(DecodedJWT decodedJWT) { ObjectMapper mapper = new ObjectMapper(); try { - map = mapper.readValue(plainTextPart, new TypeReference>() { + map = (HashMap) mapper.readValue(plainTextPart, new TypeReference>() { }); } catch (Exception e) { return 0; From 4117a6e3619b4cb82381a3e7cbbc7ed3f9615233 Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Thu, 2 Jul 2020 10:48:03 -0300 Subject: [PATCH 06/10] Fix JWT DateUtil methods (#24) --- .../src/main/java/com/genexus/JWT/utils/DateUtil.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/GeneXusJWT/src/main/java/com/genexus/JWT/utils/DateUtil.java b/GeneXusJWT/src/main/java/com/genexus/JWT/utils/DateUtil.java index 21f8175..59b3dbf 100644 --- a/GeneXusJWT/src/main/java/com/genexus/JWT/utils/DateUtil.java +++ b/GeneXusJWT/src/main/java/com/genexus/JWT/utils/DateUtil.java @@ -17,15 +17,15 @@ public String getCurrentDate() { public String currentPlusSeconds(long seconds) { DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); LocalDateTime now = LocalDateTime.now(); - now.plusSeconds(seconds); - return dtf.format(now); + LocalDateTime aux = now.plusSeconds(seconds); + return dtf.format(aux); } public String currentMinusSeconds(long seconds) { DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); LocalDateTime now = LocalDateTime.now(); - now.minusSeconds(seconds); - return dtf.format(now); + LocalDateTime aux = now.minusSeconds(seconds); + return dtf.format(aux); } /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ From 658b48fa2f4a6fc5db2525c9fadddd182740b6be Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Fri, 10 Jul 2020 15:53:47 -0300 Subject: [PATCH 07/10] Add JWT DateUtil functions (#25) --- .../java/com/genexus/JWT/utils/DateUtil.java | 67 ++++++++++++++++++- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/GeneXusJWT/src/main/java/com/genexus/JWT/utils/DateUtil.java b/GeneXusJWT/src/main/java/com/genexus/JWT/utils/DateUtil.java index 59b3dbf..d4d75b9 100644 --- a/GeneXusJWT/src/main/java/com/genexus/JWT/utils/DateUtil.java +++ b/GeneXusJWT/src/main/java/com/genexus/JWT/utils/DateUtil.java @@ -1,11 +1,15 @@ package com.genexus.JWT.utils; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoField; +import java.util.Calendar; import com.genexus.commons.DateUtilObject; -public final class DateUtil extends DateUtilObject{ +public final class DateUtil extends DateUtilObject { /******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/ public String getCurrentDate() { @@ -13,20 +17,77 @@ public String getCurrentDate() { LocalDateTime now = LocalDateTime.now(); return dtf.format(now); } - + public String currentPlusSeconds(long seconds) { DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); LocalDateTime now = LocalDateTime.now(); LocalDateTime aux = now.plusSeconds(seconds); return dtf.format(aux); } - + public String currentMinusSeconds(long seconds) { DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); LocalDateTime now = LocalDateTime.now(); LocalDateTime aux = now.minusSeconds(seconds); return dtf.format(aux); } + + public String currentPlusMinutes(long minutes) { + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); + LocalDateTime now = LocalDateTime.now(); + LocalDateTime aux = now.plusMinutes(minutes); + return dtf.format(aux); + } + + public String currentPlusHours(long hours) { + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); + LocalDateTime now = LocalDateTime.now(); + LocalDateTime aux = now.plusHours(hours); + return dtf.format(aux); + } + + public String currentPlusDays(long days) { + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); + LocalDateTime now = LocalDateTime.now(); + LocalDateTime aux = now.plusDays(days); + return dtf.format(aux); + } + + public String currentPlusMonths(int months) { + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); + LocalDateTime now = LocalDateTime.now(); + LocalDateTime aux = now.plusMonths(months); + return dtf.format(aux); + } + + public String lastDayOfCurrentMonth(String time) { + LocalTime localTime; + try { + localTime = LocalTime.parse(time, DateTimeFormatter.ofPattern("HH:mm:ss")); + } catch (DateTimeParseException e) { + this.error.setError("DU001", "Wrong format in input parameter"); + return ""; + } + + int hour = localTime.get(ChronoField.CLOCK_HOUR_OF_DAY); + int minute = localTime.get(ChronoField.MINUTE_OF_HOUR); + int second = localTime.get(ChronoField.SECOND_OF_MINUTE); + Calendar calendar = Calendar.getInstance(); + int day = calendar.getActualMaximum(Calendar.DATE); + LocalDateTime now = LocalDateTime.now(); + int year = now.getYear(); + int month = now.getMonthValue(); + String result; + try { + result = String.format("%d/%02d/%02d %02d:%02d:%02d", year, month, day, hour, minute, second); + } catch (java.util.IllegalFormatException e) { + this.error.setError("DU002", "Could not generate correct date"); + return ""; + } + return result; + + } + /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ } From bf1f5bb3f47e78d896251204d42a8cd333a51da1 Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Mon, 20 Jul 2020 11:28:40 -0300 Subject: [PATCH 08/10] DateUtil & GUID deprecation (#26) --- .../java/com/genexus/JWT/utils/DateUtil.java | 81 +++++-------------- .../main/java/com/genexus/JWT/utils/GUID.java | 9 ++- 2 files changed, 29 insertions(+), 61 deletions(-) diff --git a/GeneXusJWT/src/main/java/com/genexus/JWT/utils/DateUtil.java b/GeneXusJWT/src/main/java/com/genexus/JWT/utils/DateUtil.java index d4d75b9..fc55944 100644 --- a/GeneXusJWT/src/main/java/com/genexus/JWT/utils/DateUtil.java +++ b/GeneXusJWT/src/main/java/com/genexus/JWT/utils/DateUtil.java @@ -1,23 +1,34 @@ package com.genexus.JWT.utils; import java.time.LocalDateTime; -import java.time.LocalTime; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.time.temporal.ChronoField; -import java.util.Calendar; import com.genexus.commons.DateUtilObject; +/***** DEPRECATED OBJECT SINCE GeneXus 16 upgrade 11 ******/ + public final class DateUtil extends DateUtilObject { /******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/ + + /** + * @deprecated DateUtil object is deprecated. Use GeneXus DateTime data type + * instead + * https://wiki.genexus.com/commwiki/servlet/wiki?7370,DateTime%20data%20type + */ + @Deprecated public String getCurrentDate() { DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); LocalDateTime now = LocalDateTime.now(); return dtf.format(now); } + /** + * @deprecated DateUtil object is deprecated. Use GeneXus DateTime data type + * instead + * https://wiki.genexus.com/commwiki/servlet/wiki?7370,DateTime%20data%20type + */ + @Deprecated public String currentPlusSeconds(long seconds) { DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); LocalDateTime now = LocalDateTime.now(); @@ -25,6 +36,12 @@ public String currentPlusSeconds(long seconds) { return dtf.format(aux); } + /** + * @deprecated DateUtil object is deprecated. Use GeneXus DateTime data type + * instead + * https://wiki.genexus.com/commwiki/servlet/wiki?7370,DateTime%20data%20type + */ + @Deprecated public String currentMinusSeconds(long seconds) { DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); LocalDateTime now = LocalDateTime.now(); @@ -32,62 +49,6 @@ public String currentMinusSeconds(long seconds) { return dtf.format(aux); } - public String currentPlusMinutes(long minutes) { - DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); - LocalDateTime now = LocalDateTime.now(); - LocalDateTime aux = now.plusMinutes(minutes); - return dtf.format(aux); - } - - public String currentPlusHours(long hours) { - DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); - LocalDateTime now = LocalDateTime.now(); - LocalDateTime aux = now.plusHours(hours); - return dtf.format(aux); - } - - public String currentPlusDays(long days) { - DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); - LocalDateTime now = LocalDateTime.now(); - LocalDateTime aux = now.plusDays(days); - return dtf.format(aux); - } - - public String currentPlusMonths(int months) { - DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); - LocalDateTime now = LocalDateTime.now(); - LocalDateTime aux = now.plusMonths(months); - return dtf.format(aux); - } - - public String lastDayOfCurrentMonth(String time) { - LocalTime localTime; - try { - localTime = LocalTime.parse(time, DateTimeFormatter.ofPattern("HH:mm:ss")); - } catch (DateTimeParseException e) { - this.error.setError("DU001", "Wrong format in input parameter"); - return ""; - } - - int hour = localTime.get(ChronoField.CLOCK_HOUR_OF_DAY); - int minute = localTime.get(ChronoField.MINUTE_OF_HOUR); - int second = localTime.get(ChronoField.SECOND_OF_MINUTE); - Calendar calendar = Calendar.getInstance(); - int day = calendar.getActualMaximum(Calendar.DATE); - LocalDateTime now = LocalDateTime.now(); - int year = now.getYear(); - int month = now.getMonthValue(); - String result; - try { - result = String.format("%d/%02d/%02d %02d:%02d:%02d", year, month, day, hour, minute, second); - } catch (java.util.IllegalFormatException e) { - this.error.setError("DU002", "Could not generate correct date"); - return ""; - } - return result; - - } - /******** EXTERNAL OBJECT PUBLIC METHODS - END ********/ } diff --git a/GeneXusJWT/src/main/java/com/genexus/JWT/utils/GUID.java b/GeneXusJWT/src/main/java/com/genexus/JWT/utils/GUID.java index dd86c31..30b0ce2 100644 --- a/GeneXusJWT/src/main/java/com/genexus/JWT/utils/GUID.java +++ b/GeneXusJWT/src/main/java/com/genexus/JWT/utils/GUID.java @@ -4,9 +4,16 @@ import com.genexus.commons.GUIDObject; -public final class GUID extends GUIDObject{ +/***** DEPRECATED OBJECT SINCE GeneXus 16 upgrade 11 ******/ + +public final class GUID extends GUIDObject { /******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/ + /** + * @deprecated GUID object is deprecated. USe Genexus GUID data type instead + * https://wiki.genexus.com/commwiki/servlet/wiki?31772,GUID+data+type + */ + @Deprecated public String generate() { UUID uuid = UUID.randomUUID(); From c923bc4d23cd5af64fcb961c8e60bfaa85d149c4 Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Mon, 20 Jul 2020 11:40:03 -0300 Subject: [PATCH 09/10] Add .key & .pkcs12 extensions (#27) --- .../com/genexus/securityapicommons/keys/CertificateX509.java | 2 +- .../genexus/securityapicommons/keys/PrivateKeyManager.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/keys/CertificateX509.java b/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/keys/CertificateX509.java index 54c0d27..10143b9 100644 --- a/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/keys/CertificateX509.java +++ b/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/keys/CertificateX509.java @@ -269,7 +269,7 @@ private boolean loadPublicKeyFromFile(String path, String alias, String password return result; } if (SecurityUtils.extensionIs(path, ".pfx") || SecurityUtils.extensionIs(path, ".p12") - || SecurityUtils.extensionIs(path, ".jks")) { + || SecurityUtils.extensionIs(path, ".jks") || SecurityUtils.extensionIs(path, ".pkcs12")) { result = loadPublicKeyFromPKCS12File(path, alias, password); return result; } diff --git a/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/keys/PrivateKeyManager.java b/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/keys/PrivateKeyManager.java index 895550b..1ad5822 100644 --- a/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/keys/PrivateKeyManager.java +++ b/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/keys/PrivateKeyManager.java @@ -245,11 +245,11 @@ private boolean loadKeyFromFile(String path, String alias, String password) thro */ private boolean loadPrivateKeyFromFile(String path, String alias, String password) throws CertificateException, IOException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException { - if (SecurityUtils.extensionIs(path, ".pem")) { + if (SecurityUtils.extensionIs(path, ".pem") || SecurityUtils.extensionIs(path, ".key")) { return this.hasPrivateKey = loadPrivateKeyFromPEMFile(path); } if (SecurityUtils.extensionIs(path, ".pfx") || SecurityUtils.extensionIs(path, ".p12") - || SecurityUtils.extensionIs(path, ".jks")) { + || SecurityUtils.extensionIs(path, ".jks") || SecurityUtils.extensionIs(path, ".pkcs12")) { return this.hasPrivateKey = loadPrivateKeyFromPKCS12File(path, alias, password); } this.error.setError("PK014", "Error loading private key"); From 569aadcb74edd4d9ef3a90dcda4460bdfc9faf94 Mon Sep 17 00:00:00 2001 From: sgrampone <30872877+sgrampone@users.noreply.github.com> Date: Fri, 24 Jul 2020 14:56:28 -0300 Subject: [PATCH 10/10] Fix possible null dereference (#28) --- .../genexus/securityapicommons/utils/SecurityUtils.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/utils/SecurityUtils.java b/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/utils/SecurityUtils.java index 45b51a4..67fa30c 100644 --- a/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/utils/SecurityUtils.java +++ b/SecurityAPICommons/src/main/java/com/genexus/securityapicommons/utils/SecurityUtils.java @@ -14,8 +14,11 @@ public class SecurityUtils { public static boolean compareStrings(String one, String two) { - return one.compareToIgnoreCase(two) == 0; - + if (one != null && two != null) { + return one.compareToIgnoreCase(two) == 0; + } else { + return false; + } }