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 2018/03/22 20:57:26 UTC
svn commit: r1827528 - in /ofbiz/ofbiz-framework/branches/release17.12: ./
framework/common/webcommon/WEB-INF/ framework/security/config/
framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/
Author: jleroux
Date: Thu Mar 22 20:57:26 2018
New Revision: 1827528
URL: http://svn.apache.org/viewvc?rev=1827528&view=rev
Log:
Reverted: Token Based Authentication
(OFBIZ-9833)
This was a new feature committed the 2017-10-29 and has completely changed since.
It should not stay as is in R17.12
Modified:
ofbiz/ofbiz-framework/branches/release17.12/ (props changed)
ofbiz/ofbiz-framework/branches/release17.12/build.gradle
ofbiz/ofbiz-framework/branches/release17.12/framework/common/webcommon/WEB-INF/common-controller.xml
ofbiz/ofbiz-framework/branches/release17.12/framework/security/config/security.properties
ofbiz/ofbiz-framework/branches/release17.12/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java
Propchange: ofbiz/ofbiz-framework/branches/release17.12/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Mar 22 20:57:26 2018
@@ -10,4 +10,4 @@
/ofbiz/branches/json-integration-refactoring:1634077-1635900
/ofbiz/branches/multitenant20100310:921280-927264
/ofbiz/branches/release13.07:1547657
-/ofbiz/ofbiz-framework/trunk:1819499,1819598,1819800,1819805,1819811,1820038,1820262,1820374-1820375,1820441,1820457,1820644,1820658,1820790,1820823,1820949,1820966,1821012,1821036,1821112,1821115,1821144,1821186,1821219,1821226,1821230,1821386,1821600,1821613,1821628,1821965,1822125,1822310,1822377,1822383,1822393,1822882,1823324,1823467,1823562,1823876,1824260,1824314,1824316,1824732,1824803,1824847,1824855,1825192,1825211,1825216,1825233,1825450,1826374,1826502,1826592,1826671,1826674,1826805,1826938,1826997,1827439,1827441
+/ofbiz/ofbiz-framework/trunk:1819499,1819598,1819800,1819805,1819811,1820038,1820262,1820374-1820375,1820441,1820457,1820644,1820658,1820790,1820823,1820949,1820966,1821012,1821036,1821112,1821115,1821144,1821186,1821219,1821226,1821230,1821386,1821613,1821628,1821965,1822125,1822310,1822377,1822383,1822393,1823467,1823562,1823876,1824314,1824316,1824732,1824803,1824847,1824855,1825192,1825211,1825216,1825233,1825450,1826374,1826502,1826592,1826671,1826674,1826805,1826938,1826997,1827439
Modified: ofbiz/ofbiz-framework/branches/release17.12/build.gradle
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/branches/release17.12/build.gradle?rev=1827528&r1=1827527&r2=1827528&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/branches/release17.12/build.gradle (original)
+++ ofbiz/ofbiz-framework/branches/release17.12/build.gradle Thu Mar 22 20:57:26 2018
@@ -144,7 +144,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/branches/release17.12/framework/common/webcommon/WEB-INF/common-controller.xml
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/branches/release17.12/framework/common/webcommon/WEB-INF/common-controller.xml?rev=1827528&r1=1827527&r2=1827528&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/branches/release17.12/framework/common/webcommon/WEB-INF/common-controller.xml (original)
+++ ofbiz/ofbiz-framework/branches/release17.12/framework/common/webcommon/WEB-INF/common-controller.xml Thu Mar 22 20:57:26 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/branches/release17.12/framework/security/config/security.properties
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/branches/release17.12/framework/security/config/security.properties?rev=1827528&r1=1827527&r2=1827528&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/branches/release17.12/framework/security/config/security.properties (original)
+++ ofbiz/ofbiz-framework/branches/release17.12/framework/security/config/security.properties Thu Mar 22 20:57:26 2018
@@ -131,15 +131,3 @@ default.error.response.view=view:viewBlo
# -- If false, then no externalLoginKey parameters will be added to cross-webapp urls
security.login.externalLoginKey.enabled=true
-
-# -- 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=N
-# -- 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/branches/release17.12/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/branches/release17.12/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java?rev=1827528&r1=1827527&r2=1827528&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/branches/release17.12/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java (original)
+++ ofbiz/ofbiz-framework/branches/release17.12/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java Thu Mar 22 20:57:26 2018
@@ -18,39 +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.base.util.UtilHttp;
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.
*/
@@ -59,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,162 +150,5 @@ public class ExternalLoginKeysManager {
private static boolean isAjax(HttpServletRequest request) {
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();
-
- // The target server does not allow external login by default
- boolean useExternalServer = EntityUtilProperties.getPropertyAsBoolean("security", "use-external-server", false);
- String sourceWebappName = request.getParameter(SOURCE_SERVER_WEBAPP_NAME);
- if (!useExternalServer || sourceWebappName == null) return "success"; // Nothing to do here
-
- try {
- String userLoginId = null;
- String authorizationHeader = request.getHeader("Authorization");
- if (authorizationHeader != null) {
- Claims claims = returnsClaims(authorizationHeader);
- userLoginId = getSourceUserLoginId(claims );
- boolean jwtOK = checkJwt(authorizationHeader, userLoginId, getTargetServerUrl(request), UtilHttp.getApplicationName(request));
- 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);
- }
-
- 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;
- }
}