svn commit: r1833510 - in /ofbiz/ofbiz-framework/trunk: ./ framework/common/webcommon/WEB-INF/ framework/security/config/ framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r1833510 - in /ofbiz/ofbiz-framework/trunk: ./ framework/common/webcommon/WEB-INF/ framework/security/config/ framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/

jleroux@apache.org
Author: jleroux
Date: Thu Jun 14 14:37:24 2018
New Revision: 1833510

URL: http://svn.apache.org/viewvc?rev=1833510&view=rev
Log:
Reverted: Navigate from a domain to another with automated signed in
authentication
(OFBIZ-10307)

This reverts the work done previously for OFBIZ-9833 and OFBIZ-10206
Most parts of it will actually be reused later in a patch. By reverting it will
allow to provide a patch for others to review

Modified:
    ofbiz/ofbiz-framework/trunk/build.gradle
    ofbiz/ofbiz-framework/trunk/framework/common/webcommon/WEB-INF/common-controller.xml
    ofbiz/ofbiz-framework/trunk/framework/security/config/security.properties
    ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java

Modified: ofbiz/ofbiz-framework/trunk/build.gradle
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/build.gradle?rev=1833510&r1=1833509&r2=1833510&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/build.gradle (original)
+++ ofbiz/ofbiz-framework/trunk/build.gradle Thu Jun 14 14:37:24 2018
@@ -149,7 +149,6 @@ dependencies {
     compile 'org.zapodot:jackson-databind-java-optional:2.6.1'
     compile 'oro:oro:2.0.8'
     compile 'wsdl4j:wsdl4j:1.6.3'
-    compile 'io.jsonwebtoken:jjwt:0.9.0'
     compile 'org.jsoup:jsoup:1.11.2'
 
     // ofbiz unit-test compile libs

Modified: ofbiz/ofbiz-framework/trunk/framework/common/webcommon/WEB-INF/common-controller.xml
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/common/webcommon/WEB-INF/common-controller.xml?rev=1833510&r1=1833509&r2=1833510&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/common/webcommon/WEB-INF/common-controller.xml (original)
+++ ofbiz/ofbiz-framework/trunk/framework/common/webcommon/WEB-INF/common-controller.xml Thu Jun 14 14:37:24 2018
@@ -31,7 +31,6 @@ under the License.
         <event name="checkRequestHeaderLogin" type="java" path="org.apache.ofbiz.webapp.control.LoginWorker" invoke="checkRequestHeaderLogin"/>
         <event name="checkServletRequestRemoteUserLogin" type="java" path="org.apache.ofbiz.webapp.control.LoginWorker" invoke="checkServletRequestRemoteUserLogin"/>
         <event name="checkExternalLoginKey" type="java" path="org.apache.ofbiz.webapp.control.ExternalLoginKeysManager" invoke="checkExternalLoginKey"/>
-        <event name="externalServerLoginCheck" type="java" path="org.apache.ofbiz.webapp.control.ExternalLoginKeysManager" invoke="externalServerLoginCheck"/>
         <event name="checkProtectedView" type="java" path="org.apache.ofbiz.webapp.control.ProtectViewWorker" invoke="checkProtectedView"/>
         <event name="extensionConnectLogin" type="java" path="org.apache.ofbiz.webapp.control.LoginWorker" invoke="extensionConnectLogin"/>
     </preprocessor>

Modified: ofbiz/ofbiz-framework/trunk/framework/security/config/security.properties
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/security/config/security.properties?rev=1833510&r1=1833509&r2=1833510&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/security/config/security.properties (original)
+++ ofbiz/ofbiz-framework/trunk/framework/security/config/security.properties Thu Jun 14 14:37:24 2018
@@ -134,12 +134,3 @@ security.login.externalLoginKey.enabled=
 
 # -- Security key used to encrypt and decrypt the autogenerated password in forgot password functionality.
 login.secret_key_string=Secret Key
-
-### To have this working, an example of the change needed on the source server is available in OFBIZ-10206-external-server-test-example.patch
-# -- If true, then it's possible to connect to another webapp on another server w/o signing in
-# -- This needs to be changed on both the source server and the target server
-use-external-server=Y
-# -- Name of the external server (DNS) ex: demo-trunk.ofbiz.apache.org where the port is not needed, or localhost:8443 (default) for local tests (not using the same webapp)
-external-server-name=demo-trunk.ofbiz.apache.org
-# -- Time To Live of the token send to the external server in seconds
-external-server-token-duration=30

Modified: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java?rev=1833510&r1=1833509&r2=1833510&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java (original)
+++ ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java Thu Jun 14 14:37:24 2018
@@ -18,38 +18,21 @@
  */
 package org.apache.ofbiz.webapp.control;
 
-import java.security.Key;
-import java.util.Date;
 import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 
-import javax.crypto.spec.SecretKeySpec;
-import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
-import javax.xml.bind.DatatypeConverter;
 
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.entity.Delegator;
 import org.apache.ofbiz.entity.DelegatorFactory;
-import org.apache.ofbiz.entity.GenericEntityException;
 import org.apache.ofbiz.entity.GenericValue;
-import org.apache.ofbiz.entity.util.EntityQuery;
-import org.apache.ofbiz.entity.util.EntityUtilProperties;
 import org.apache.ofbiz.service.LocalDispatcher;
 import org.apache.ofbiz.webapp.WebAppUtil;
 
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.ExpiredJwtException;
-import io.jsonwebtoken.JwtBuilder;
-import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.MalformedJwtException;
-import io.jsonwebtoken.SignatureAlgorithm;
-import io.jsonwebtoken.SignatureException;
-import io.jsonwebtoken.UnsupportedJwtException;
-
 /**
  * This class manages the authentication tokens that provide single sign-on authentication to the OFBiz applications.
  */
@@ -58,19 +41,6 @@ public class ExternalLoginKeysManager {
     private static final String EXTERNAL_LOGIN_KEY_ATTR = "externalLoginKey";
     // This Map is keyed by the randomly generated externalLoginKey and the value is a UserLogin GenericValue object
     private static final Map<String, GenericValue> externalLoginKeys = new ConcurrentHashMap<>();
-    public static final String SOURCE_SERVER_WEBAPP_NAME = "sourceServerWebappName";
-    // This works the same way than externalLoginKey but between 2 servers, not 2 webapps on the same server.
-    // The Single Sign On (SSO) is ensured by a JWT token, then all is handled as normal by a session on the reached server.
-    // The servers may or may not share a database but the 2 loginUserIds must be the same.
-    
-    // OOTB the JWT masterSecretKey is not properly initialised and can not be OOTB.
-    // As we sign on on several servers, so have different sessions, we can't use the externalLoginKey way to create the JWT masterSecretKey.
-    // IMO the best way to create the JWT masterSecretKey is to use a temporary way to load in a static final key when compiling.
-    // This is simple and most secure. See OFBIZ-9833 for more, notably https://s.apache.org/cFeK
-    
-    // Because it will contain the ExternalServerJwtMasterSecretKey value;
-    // you should not let the ExternalLoginKeysManager.java file on a production server after its compilation
-    private static final String ExternalServerJwtMasterSecretKey = "ExternalServerJwtMasterSecretKey";
 
     /**
      * Gets (and creates if necessary) an authentication token to be used for an external login parameter.
@@ -181,159 +151,4 @@ public class ExternalLoginKeysManager {
        return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
     }
     
-    public static String externalServerLoginCheck(HttpServletRequest request, HttpServletResponse response) {
-        Delegator delegator = (Delegator) request.getAttribute("delegator");
-        HttpSession session = request.getSession();
-
-        try {
-            String userLoginId = null;
-            String authorizationHeader = request.getHeader("Authorization");
-            if (authorizationHeader != null) {
-                Claims claims = returnsClaims(authorizationHeader);
-                userLoginId = getSourceUserLoginId(claims );
-                boolean jwtOK = checkJwt(authorizationHeader, userLoginId, "", "");
-                if (!jwtOK) {
-                    // Something unexpected happened here
-                    Debug.logWarning("*** There was a problem with the JWT token, not signin in the user login " + userLoginId, module);
-                    return "success";
-                }
-            } else {
-                // Nothing to do here
-                return "success";
-            }
-
-            
-            GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", userLoginId).queryOne();
-            if (userLogin != null) {
-                // Check it's the right tenant in case username and password are the same in different tenants
-                // Not sure this is really useful in the case of external server, should not hurt anyway
-                LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
-                String oldDelegatorName = delegator.getDelegatorName();
-                ServletContext servletContext = session.getServletContext();
-                if (!oldDelegatorName.equals(userLogin.getDelegator().getDelegatorName())) {
-                    delegator = DelegatorFactory.getDelegator(userLogin.getDelegator().getDelegatorName());
-                    dispatcher = WebAppUtil.makeWebappDispatcher(servletContext, delegator);
-                    LoginWorker.setWebContextObjects(request, response, delegator, dispatcher);
-                }
-                String enabled = userLogin.getString("enabled");
-                if (enabled == null || "Y".equals(enabled)) {
-                    userLogin.set("hasLoggedOut", "N");
-                    userLogin.store();
-                }
-            } else {
-                Debug.logWarning("*** There was a problem with the JWT token. Could not find userLogin " + userLoginId, module);
-            }
-            LoginWorker.doBasicLogin(userLogin, request);
-        } catch (GenericEntityException e) {
-            Debug.logError(e, "Cannot get autoUserLogin information: " + e.getMessage(), module);
-        }
-
-        // make sure the autoUserLogin is set to the same and that the client cookie has the correct userLoginId
-        LoginWorker.autoLoginSet(request, response);
-        
-        return "success";
-    }
-    
-    /**
-     * Generate and return a JWT key
-     *
-     * @param id is an Id, I suggest userLoginId
-     * @param issuer is who/what issued the token. I suggest the server DNS
-     * @param subject is the subject of the token. I suggest the destination webapp
-     * @param ttlMillis the expiration time
-     * @return a JWT token
-     */
-    public static String createJwt(String id, String issuer, String subject, long ttlMillis) {
-        //The JWT signature algorithm we will be using to sign the token
-        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS512;
-
-        long nowMillis = System.currentTimeMillis();
-        Date now = new Date(nowMillis);
-
-        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(ExternalServerJwtMasterSecretKey);
-        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
-        //Let's set the JWT Claims
-        JwtBuilder builder = Jwts.builder().setId(id)
-                .setIssuedAt(now)
-                .setSubject(subject)
-                .setIssuer(issuer)
-                .setIssuedAt(now)
-                .signWith(signatureAlgorithm, signingKey);
-
-        //if it has been specified, let's add the expiration date, this should always be true
-        if (ttlMillis >= 0) {
-            long expMillis = nowMillis + ttlMillis;
-            Date exp = new Date(expMillis);
-            builder.setExpiration(exp);
-        }
-
-        //Builds the JWT and serialises it to a compact, URL-safe string
-        return builder.compact();
-    }
-    
-    /**
-     * Reads and validates a JWT token
-     * Throws a SignatureException if it is not a signed JWS (as expected) or has been tampered
-     * @param jwt a JWT token
-     * @param id is an Id, I suggest userLoginId
-     * @param issuer is who/what issued the token. I suggest the server DNS
-     * @param subject is the subject of the token. I suggest the destination webapp
-     * @return true if the JWT token corresponds to the one sent and is not expired
-     */
-    private static boolean checkJwt(String jwt, String id, String issuer, String subject) {
-        //The JWT signature algorithm is using this to sign the token
-        Claims claims = returnsClaims(jwt);
-
-        long nowMillis = System.currentTimeMillis();
-        Date now = new Date(nowMillis);
-
-        return claims.getId().equals(id)
-                && claims.getIssuer().equals(issuer)
-                && claims.getSubject().equals(subject)
-                && claims.getExpiration().after(now);
-    }
-
-    /**
-     * @param jwt a JWT token
-     * @return claims the claims
-     * @throws ExpiredJwtException
-     * @throws UnsupportedJwtException
-     * @throws MalformedJwtException
-     * @throws SignatureException
-     * @throws IllegalArgumentException
-     */
-    private static Claims returnsClaims(String jwt) throws ExpiredJwtException, UnsupportedJwtException,
-            MalformedJwtException, SignatureException, IllegalArgumentException {
-        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS512;
-
-        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(ExternalServerJwtMasterSecretKey);
-        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
-
-        //This line will throw a SignatureException if it is not a signed JWS (as expected) or has been tampered
-        Claims claims = Jwts.parser()
-           .setSigningKey(signingKey)
-           .parseClaimsJws(jwt).getBody();
-        return claims;
-    }
-
-    private static String getSourceUserLoginId(Claims claims) {
-        return claims.getId();
-    }
-    
-    public static String getTargetServerUrl(HttpServletRequest request) {
-        String targetServerUrl = "";
-        Delegator delegator = (Delegator) request.getAttribute("delegator");
-        if (delegator != null && "Y".equals(EntityUtilProperties.getPropertyValue("security", "use-external-server", "N", delegator))) {
-            targetServerUrl = EntityUtilProperties.getPropertyValue("security", "external-server-name", "localhost:8443", delegator);
-            targetServerUrl = "https://" + targetServerUrl;
-        }
-        return targetServerUrl;
-    }
-    
-    public static long getJwtTokenTimeToLive(HttpServletRequest request) {
-        Delegator delegator = (Delegator) request.getAttribute("delegator");
-        if (delegator != null) return 1000 * Long.parseLong(EntityUtilProperties.getPropertyValue("security", "external-server-token-duration", "30", delegator));
-        else return 1000 * 30;
-    }
-
 }