diff --git a/.classpath b/.classpath
index c40c8e2..d0d8276 100644
--- a/.classpath
+++ b/.classpath
@@ -1,5 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -10,18 +21,8 @@
+
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index ec4300d..2f5cc74 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,5 +1,8 @@
eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs
index f897a7f..4528a36 100644
--- a/.settings/org.eclipse.m2e.core.prefs
+++ b/.settings/org.eclipse.m2e.core.prefs
@@ -1,4 +1,4 @@
-activeProfiles=
+activeProfiles=gcube-developer
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
diff --git a/pom.xml b/pom.xml
index 10a66b6..0c5ae6d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
org.gcube.portal
threadlocal-vars-cleaner
- 2.1.1
+ 2.2.0
jar
threadlocal-vars-cleaner
This component clean the Smartgears ThreadLocal variables each time a new Thread is assigned to a request from tomcat thread pool
@@ -61,11 +61,22 @@
portal-manager
provided
+
+ org.gcube.portal
+ oidc-library-portal
+ [0.1.0,)
+ provided
+
com.liferay.portal
portal-service
provided
+
+ javax.portlet
+ portlet-api
+ provided
+
org.slf4j
slf4j-api
@@ -81,21 +92,21 @@
threadlocal-vars-cleaner-${project.version}
-
- org.apache.maven.plugins
- maven-war-plugin
-
-
- compile
-
- exploded
-
-
-
-
- ${webappDirectory}
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
org.apache.maven.plugins
maven-compiler-plugin
diff --git a/src/main/java/org/gcube/portal/threadlocalexec/SmartGearsPortalValve.java b/src/main/java/org/gcube/portal/threadlocalexec/SmartGearsPortalValve.java
index c916f06..3ec29af 100644
--- a/src/main/java/org/gcube/portal/threadlocalexec/SmartGearsPortalValve.java
+++ b/src/main/java/org/gcube/portal/threadlocalexec/SmartGearsPortalValve.java
@@ -3,11 +3,14 @@ package org.gcube.portal.threadlocalexec;
import static org.gcube.common.authorization.client.Constants.authorizationService;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
@@ -15,117 +18,237 @@ import org.apache.catalina.valves.ValveBase;
import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
+import org.gcube.common.authorization.library.provider.UmaJWTProvider;
import org.gcube.common.authorization.library.provider.UserInfo;
import org.gcube.common.portal.PortalContext;
import org.gcube.common.scope.api.ScopeProvider;
-import org.gcube.common.scope.impl.ScopeBean;
+import org.gcube.oidc.rest.JWTToken;
+import org.gcube.oidc.rest.OpenIdConnectConfiguration;
+import org.gcube.oidc.rest.OpenIdConnectRESTHelper;
+import org.gcube.portal.oidc.lr62.JWTTokenUtil;
+import org.gcube.portal.oidc.lr62.LiferayOpenIdConnectConfiguration;
+import org.gcube.portal.oidc.lr62.OIDCTokenCacheProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.liferay.portal.model.User;
import com.liferay.portal.service.UserLocalServiceUtil;
+
/**
*
* @author Massimiliano Assante, CNR ISTI
* @author Lucio Lelii, CNR ISTI
+ * @author Mauro Mugnaini, Nubisware S.r.l.
*
*/
-public class SmartGearsPortalValve extends ValveBase {
- private static final Logger _log = LoggerFactory.getLogger(SmartGearsPortalValve.class);
- private final static String DEFAULT_ROLE = "OrganizationMember";
- private final static String LIFERAY_POLLER_CONTEXT = "poller/receive";
+public class SmartGearsPortalValve extends ValveBase {
+ private static final Logger _log = LoggerFactory.getLogger(SmartGearsPortalValve.class);
+ private final static String DEFAULT_ROLE = "OrganizationMember";
+ private final static String LIFERAY_POLLER_CONTEXT = "poller/receive";
- @Override
- public void invoke(Request req, Response resp) throws IOException, ServletException {
- SecurityTokenProvider.instance.reset();
- ScopeProvider.instance.reset();
- AuthorizationProvider.instance.reset();
- //_log.trace("SmartGearsPortalValve SecurityTokenProvider and AuthorizationProvider reset OK");
- if (req instanceof HttpServletRequest) {
- HttpServletRequest request = (HttpServletRequest) req;
- if (!req.getRequestURL().toString().endsWith(LIFERAY_POLLER_CONTEXT)) { //avoid calling gCube auth service for liferay internal poller
- PortalContext context = PortalContext.getConfiguration();
- String scope = context.getCurrentScope(request);
- String username = getCurrentUsername(request);
- if (scope != null && username != null && validateContext(scope)) {
- String userToken = null;
- try {
- ScopeProvider.instance.set(scope);
- userToken = authorizationService().resolveTokenByUserAndContext(username, scope);
- SecurityTokenProvider.instance.set(userToken);
- }
- catch (ObjectNotFound ex) {
- userToken = generateAuthorizationToken(username, scope);
- SecurityTokenProvider.instance.set(userToken);
- _log.debug("generateAuthorizationToken OK for " + username + " in scope " + scope);
- }
- catch (Exception e) {
- _log.error("Something went wrong in generating token for " + username + " in scope " + scope);
- e.printStackTrace();
- }
- //_log.trace("Security token set OK for " + username + " in scope " + scope);
- }
- }
- }
- getNext().invoke(req, resp);
- }
-
- /**
- *
- * @param context
- * @return true if is the context is syntactically valid
- */
- private static boolean validateContext(String context) {
- String separator = "/";
- if (!context.matches("\\S+"))
- return false;
- String[] components=context.split(separator);
- if (components.length<2 || components.length>4)
- return false;
- return true;
- }
+ @Override
+ public void invoke(Request req, Response resp) throws IOException, ServletException {
+ SecurityTokenProvider.instance.reset();
+ ScopeProvider.instance.reset();
+ AuthorizationProvider.instance.reset();
+ UmaJWTProvider.instance.reset();
+ //_log.trace("SmartGearsPortalValve SecurityTokenProvider and AuthorizationProvider reset OK");
+ if (req instanceof HttpServletRequest) {
+ HttpServletRequest request = (HttpServletRequest) req;
+ if (!req.getRequestURL().toString().endsWith(LIFERAY_POLLER_CONTEXT)) { //avoid calling gCube auth service for liferay internal poller
+ PortalContext context = PortalContext.getConfiguration();
+ String scope = context.getCurrentScope(request);
+ String username = getCurrentUsername(request);
+ if (scope != null && username != null && validateContext(scope)) {
+ String userToken = null;
+ try {
+ ScopeProvider.instance.set(scope);
+ userToken = authorizationService().resolveTokenByUserAndContext(username, scope);
+ SecurityTokenProvider.instance.set(userToken);
+ } catch (ObjectNotFound ex) {
+ userToken = generateAuthorizationToken(username, scope);
+ SecurityTokenProvider.instance.set(userToken);
+ _log.debug("generateAuthorizationToken OK for " + username + " in scope " + scope);
+ } catch (Exception e) {
+ _log.error("Something went wrong in generating token for " + username + " in scope " + scope);
+ e.printStackTrace();
+ }
+ checkUMATicket(request, scope);
- /**
- *
- * @param username
- * @param scope
- * @throws Exception
- */
- private static String generateAuthorizationToken(String username, String scope) {
- List userRoles = new ArrayList<>();
- userRoles.add(DEFAULT_ROLE);
- String token;
- try {
- token = authorizationService().generateUserToken(new UserInfo(username, userRoles), scope);
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- return token;
- }
+ //_log.trace("Security token set OK for " + username + " in scope " + scope);
+ }
+ }
+ }
+ getNext().invoke(req, resp);
+ }
- /**
- *
- * @param httpServletRequest the httpServletRequest object
- * @return the instance of the user
- * @see GCubeUser
- */
- public static String getCurrentUsername(HttpServletRequest httpServletRequest) {
- String userIdNo = httpServletRequest.getHeader(PortalContext.USER_ID_ATTR_NAME);
- if (userIdNo != null && userIdNo.compareTo("undefined") != 0) {
- long userId = -1;
- try {
- userId = Long.parseLong(userIdNo);
- return UserLocalServiceUtil.getUser(userId).getScreenName();
- } catch (NumberFormatException e) {
- _log.error("The userId is not a number -> " + userIdNo);
- return null;
- } catch (Exception e) {
- _log.error("The userId does not belong to any user -> " + userIdNo);
- return null;
- }
- }
- return null;
- }
+ private void checkUMATicket(HttpServletRequest request, String scope) {
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ if (_log.isDebugEnabled()) {
+ _log.debug("Session is null");
+ }
+ return;
+ }
+ if (_log.isTraceEnabled()) {
+ _log.trace("Session details: id=" + session.getId() + ", instance=" + session);
+ }
+ String urlEncodedScope = null;
+ try {
+ urlEncodedScope = URLEncoder.encode(scope, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ _log.error("Cannot URL encode scope", e);
+ return;
+ }
+ if (_log.isDebugEnabled()) {
+ _log.debug("URL encoded scope is: " + urlEncodedScope);
+ _log.debug("Getting UMA token from session");
+ }
+ JWTToken umaToken = JWTTokenUtil.getUMAFromSession(session);
+ if (umaToken == null) {
+ if (_log.isDebugEnabled()) {
+ _log.debug("UMA token not found in session");
+ }
+ if (_log.isDebugEnabled()) {
+ _log.debug("Getting current user");
+ }
+ User user = getCurrentUser(request);
+ if (user == null) {
+ _log.error("Current user not found, cannot continue");
+ return;
+ }
+ if (_log.isDebugEnabled()) {
+ _log.debug("Trying to get UMA token from cache proxy");
+ }
+ umaToken = OIDCTokenCacheProxy.getInstance().getUMAToken(user, session);
+ if (umaToken == null || !umaToken.getAud().contains(urlEncodedScope)) {
+ if (umaToken == null) {
+ if (_log.isDebugEnabled()) {
+ _log.debug("UMA token is null. Getting new one...");
+ }
+ } else {
+ _log.info("UMA token for another scope (" + umaToken.getAud() + "). Getting new one for scope: "
+ + urlEncodedScope);
+ }
+ if (_log.isDebugEnabled()) {
+ _log.debug("Getting OIDC token from session");
+ }
+ JWTToken authToken = JWTTokenUtil.getOIDCFromSession(session);
+ if (authToken == null) {
+ if (_log.isDebugEnabled()) {
+ _log.debug("OIDC token not found in session. Trying to get it from cache proxy");
+ }
+ authToken = getOIDCTokeFromProxyAndSetInSession(user, request, session);
+ if (authToken == null) {
+ _log.error("OIDC token is null, cannot continue");
+ return;
+ } else {
+ if (_log.isDebugEnabled()) {
+ _log.debug("OIDC token found in cache proxy");
+ }
+ }
+ }
+ _log.info("Getting UMA token from OIDC endpoint for scope: " + urlEncodedScope);
+ OpenIdConnectConfiguration configuration = LiferayOpenIdConnectConfiguration.getConfiguration(request);
+ try {
+ // TODO: handle the token expired case and renew it with refresh token.
+ umaToken = OpenIdConnectRESTHelper.queryUMAToken(configuration.getTokenUrl(),
+ authToken.getAsBearer(),
+ urlEncodedScope, null);
+ } catch (Exception e) {
+ _log.error("Getting UMA token from server", e);
+ return;
+ }
+ if (_log.isDebugEnabled()) {
+ _log.debug("Setting UMA token in cache proxy");
+ }
+ OIDCTokenCacheProxy.getInstance().setRPTToken(user, session, umaToken);
+ if (_log.isDebugEnabled()) {
+ _log.debug("Setting UMA token in session");
+ }
+ JWTTokenUtil.putUMAInSession(umaToken, session);
+ }
+ }
+ if (_log.isDebugEnabled()) {
+ _log.debug("Setting UMA token in UMA JWT provider");
+ }
+ UmaJWTProvider.instance.set(umaToken.getRaw());
+ }
+
+ private JWTToken getOIDCTokeFromProxyAndSetInSession(User user, HttpServletRequest request, HttpSession session) {
+ JWTToken token = OIDCTokenCacheProxy.getInstance().getOIDCToken(user, session);
+ if (token == null) {
+ _log.warn("OIDC token is null also in cache proxy!");
+ } else {
+ if (_log.isDebugEnabled()) {
+ _log.debug("Setting OIDC token took from cache proxy in session");
+ }
+ JWTTokenUtil.putOIDCInSession(token, session);
+ }
+ return token;
+ }
+
+ /**
+ *
+ * @param context
+ * @return true if is the context is syntactically valid
+ */
+ private static boolean validateContext(String context) {
+ String separator = "/";
+ if (!context.matches("\\S+"))
+ return false;
+ String[] components = context.split(separator);
+ if (components.length < 2 || components.length > 4)
+ return false;
+ return true;
+ }
+
+ /**
+ *
+ * @param username
+ * @param scope
+ * @throws Exception
+ */
+ private static String generateAuthorizationToken(String username, String scope) {
+ List userRoles = new ArrayList<>();
+ userRoles.add(DEFAULT_ROLE);
+ String token;
+ try {
+ token = authorizationService().generateUserToken(new UserInfo(username, userRoles), scope);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ return token;
+ }
+
+ /**
+ *
+ * @param httpServletRequest the httpServletRequest object
+ * @return the instance of the user
+ * @see GCubeUser
+ */
+ public static String getCurrentUsername(HttpServletRequest httpServletRequest) {
+ User user = getCurrentUser(httpServletRequest);
+ return user != null ? user.getScreenName() : null;
+ }
+
+ public static User getCurrentUser(HttpServletRequest httpServletRequest) {
+ String userIdNo = httpServletRequest.getHeader(PortalContext.USER_ID_ATTR_NAME);
+ if (userIdNo != null && userIdNo.compareTo("undefined") != 0) {
+ long userId = -1;
+ try {
+ userId = Long.parseLong(userIdNo);
+ return UserLocalServiceUtil.getUser(userId);
+ } catch (NumberFormatException e) {
+ _log.error("The userId is not a number -> " + userIdNo);
+ return null;
+ } catch (Exception e) {
+ _log.error("The userId does not belong to any user -> " + userIdNo);
+ return null;
+ }
+ }
+ return null;
+ }
}
-