You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by jl...@apache.org on 2022/12/15 09:15:37 UTC

[ofbiz-framework] branch trunk updated: Fixed: JWT Authentication Error (OFBIZ-12724)

This is an automated email from the ASF dual-hosted git repository.

jleroux pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 2ec3d24299 Fixed: JWT Authentication Error (OFBIZ-12724)
2ec3d24299 is described below

commit 2ec3d24299eb110a6d696046ef51a1ebea37ef74
Author: Jacques Le Roux <ja...@les7arts.com>
AuthorDate: Thu Dec 15 09:28:16 2022 +0100

    Fixed: JWT Authentication Error (OFBIZ-12724)
    
    Ensures the length of the secret is at least 512 bit long
    https://www.rfc-editor.org/rfc/rfc7518#page-7
    https://javadoc.io/doc/com.auth0/java-jwt/latest/com/auth0/jwt/algorithms/Algorithm.html#HMAC512
    We should follow the rule and give a 512 bit key by default and provide
    validation based on the same rule.
    
    jleroux:
    based on recommendation by Les Hazlewood (JJWT founder, Apache Shiro founder):
    https://github.com/jhipster/generator-jhipster/issues/8165#issuecomment-416246549
    I used a 512 bits key I created using https://www.allkeysgenerator.com
    (Encryption key mode).
    But I got this error:
    EntitySaxReader               |E| Fatal Error reading XML on line 23, column 155
    org.xml.sax.SAXParseException: The reference to entity "F" must end with the ';'
    delimiter. It was due to SSOJWTDemoData content. So I removed security.token.key
    from this file and used only the property in security.properties.
    
    Thanks: Ayan Farooqui for report and suggestion
---
 framework/security/config/security.properties                 | 11 +++++++----
 framework/security/data/SSOJWTDemoData.xml                    |  1 -
 .../src/docs/asciidoc/_include/sy-password-and-JWT.adoc       |  7 +++----
 .../main/java/org/apache/ofbiz/webapp/control/JWTManager.java |  8 ++++++--
 4 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/framework/security/config/security.properties b/framework/security/config/security.properties
index b7acb53346..2222fc22d8 100644
--- a/framework/security/config/security.properties
+++ b/framework/security/config/security.properties
@@ -141,17 +141,20 @@ security.login.externalLoginKey.enabled=true
 
 # -- Security key used to encrypt and decrypt the autogenerated password in forgot password functionality.
 #    Read Passwords and JWT (JSON Web Tokens) usage documentation to choose the way you want to store this key
-login.secret_key_string=login.secret_key_string
+#    The key must be 512 bits (ie 64 chars) as we use HMAC512 to create the token, cf. OFBIZ-12724
+login.secret_key_string=p2s5u8x/A?D(G+KbPeShVmYq3t6w9z$B&E)H@McQfTjWnZr4u7x!A%D*F-JaNdRg
 
 # -- Time To Live of the token send to the external server in seconds
 security.jwt.token.expireTime=1800
 
 # -- Enables the internal Single Sign On feature which allows a token based login between OFBiz instances
-# -- To make this work you also have to configure a secret key with security.token.key
+#    To make this work you also have to configure a secret key with security.token.key
 security.internal.sso.enabled=false
 
-# -- The secret key for the JWT token signature. Read Passwords and JWT (JSON Web Tokens) usage documentation to choose the way you want to store this key
-security.token.key=security.token.key
+# -- The secret key for the JWT token signature.
+#    Read Passwords and JWT (JSON Web Tokens) usage documentation to choose the way you want to store this key
+#    The key must be 512 bits (ie 64 chars) as we use HMAC512 to create the token, cf. OFBIZ-12724
+security.token.key=%D*G-JaNdRgUkXp2s5v8y/B?E(H+MbPeShVmYq3t6w9z$C&F)J@NcRfTjWnZr4u7
 
 # -- List of domains or IP addresses to be checked to prevent Host Header Injection,
 # -- no spaces after commas,no wildcard, can be extended of course...
diff --git a/framework/security/data/SSOJWTDemoData.xml b/framework/security/data/SSOJWTDemoData.xml
index 5e0e8823bb..27eb0f1eab 100644
--- a/framework/security/data/SSOJWTDemoData.xml
+++ b/framework/security/data/SSOJWTDemoData.xml
@@ -20,6 +20,5 @@ under the License.
 
 <entity-engine-xml>
     <SystemProperty systemResourceId="security" systemPropertyId="security.internal.sso.enabled" systemPropertyValue="false"/>
-    <SystemProperty systemResourceId="security" systemPropertyId="security.token.key" systemPropertyValue="security.token.key"/>
     <SystemProperty systemResourceId="security" systemPropertyId="SameSiteCookieAttribute" systemPropertyValue="strict"/>
 </entity-engine-xml>
diff --git a/framework/security/src/docs/asciidoc/_include/sy-password-and-JWT.adoc b/framework/security/src/docs/asciidoc/_include/sy-password-and-JWT.adoc
index 2bd20d774f..c63a708ecc 100644
--- a/framework/security/src/docs/asciidoc/_include/sy-password-and-JWT.adoc
+++ b/framework/security/src/docs/asciidoc/_include/sy-password-and-JWT.adoc
@@ -64,7 +64,7 @@ You might prefer to use pair of public/private keys, for now by default OFBiz us
 . We recommend to not use an environment variable as those can be considered weak:
 * http://movingfast.io/articles/environment-variables-considered-harmful
 * https://security.stackexchange.com/questions/49725/is-it-really-secure-to-store-api-keys-in-environment-variables
-    
+
 . You may want to tie the encryption key to the logged in user. This is used by the password recreation feature. The JWT secret key is salted with a combination of the current logged in user and her/his password. This is a simple and effective safe way.
 . Use a https://tools.ietf.org/html/rfc7519#section-4.1.7[JTI] (JWT ID). A JTI prevents a JWT from being replayed. This https://auth0.com/blog/blacklist-json-web-token-api-keys/[auth0 blog article get deeper in that].  The same is kinda achieved with the password recreation feature. When the user log in after the new password creation, the password has already been  changed. So the link (in the sent email) containing the JWT for the creation of the new password can't be reused.
 . Tie the encryption key to the hardware. You can refer to this https://en.wikipedia.org/wiki/Hardware_security_module[Wikipedia page] for more information.
@@ -86,7 +86,7 @@ The _security.properties_ file contains five related properties:
 
     # -- Security key used to encrypt and decrypt the autogenerated password in forgot password functionality.
     #    Read Passwords and JWT (JSON Web Tokens) usage documentation to choose the way you want to store this key
-    login.secret_key_string=login.secret_key_string
+    login.secret_key_string=p2s5u8x/A?D(G+KbPeShVmYq3t6w9z$B&E)H@McQfTjWnZr4u7x!A%D*F-JaNdRg
 
     # -- Time To Live of the token send to the external server in seconds
     security.jwt.token.expireTime=1800
@@ -96,14 +96,13 @@ The _security.properties_ file contains five related properties:
     security.internal.sso.enabled=false
 
     # -- The secret key for the JWT token signature. Read Passwords and JWT (JSON Web Tokens) usage documentation to choose the way you want to store this key
-    security.token.key=security.token.key
+    security.token.key=D*G-JaNdRgUkXp2s5v8y/B?E(H+MbPeShVmYq3t6w9z$C&F)J@NcRfTjWnZr4u7
 
 
 There are also SSO related SystemProperties in __SSOJWTDemoData.xml__:
 [source,xml]
 ----
     <SystemProperty systemResourceId="security" systemPropertyId="security.internal.sso.enabled" systemPropertyValue="false"/>
-    <SystemProperty systemResourceId="security" systemPropertyId="security.token.key" systemPropertyValue="security.token.key"/>
     <SystemProperty systemResourceId="security" systemPropertyId="SameSiteCookieAttribute" systemPropertyValue="strict"/>
 ----
 
diff --git a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/JWTManager.java b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/JWTManager.java
index 6b9f17e2ab..758ec1e571 100644
--- a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/JWTManager.java
+++ b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/JWTManager.java
@@ -33,6 +33,7 @@ import org.apache.ofbiz.base.util.StringUtil;
 import org.apache.ofbiz.base.util.UtilDateTime;
 import org.apache.ofbiz.base.util.UtilHttp;
 import org.apache.ofbiz.base.util.UtilMisc;
+import org.apache.ofbiz.base.util.UtilProperties;
 import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.entity.Delegator;
 import org.apache.ofbiz.entity.DelegatorFactory;
@@ -140,7 +141,10 @@ public class JWTManager {
      */
 
     public static String getJWTKey(Delegator delegator, String salt) {
-        String key = EntityUtilProperties.getPropertyValue("security", "security.token.key", delegator);
+        String key = UtilProperties.getPropertyValue("security", "security.token.key");
+        if (key.length() < 64) { // The key must be 512 bits (ie 64 chars)  as we use HMAC512 to create the token, cf. OFBIZ-12724
+            throw new SecurityException("The JWT secret key is too short. It must be at least 512 bites.");
+        }
         if (salt != null) {
             return StringUtil.toHexString(salt.getBytes()) + key;
         }
@@ -257,7 +261,7 @@ public class JWTManager {
 
     /**
      * Validates the provided token using a salt to recreate the key from the secret
-     * If the token is valid it will get the conteined claims and return them.
+     * If the token is valid it will get the contained claims and return them.
      * If token validation failed it will return an error.
      * @param delegator
      * @param jwtToken