From ec3fe3ddca2d3e8e58d2e4a6127aa69f14ee9389 Mon Sep 17 00:00:00 2001 From: "massimiliano.assante" Date: Thu, 2 Feb 2017 17:21:49 +0000 Subject: [PATCH] ready to release git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/user/my-vres@142111 82a268e6-3cf1-43bd-a215-b396298e98cf --- .settings/org.eclipse.wst.common.component | 2 +- .tern-project | 18 ++- pom.xml | 19 +++ .../portlet/user/my_vres/client/MyVREs.java | 8 +- .../user/my_vres/client/MyVREsService.java | 2 +- .../my_vres/client/MyVREsServiceAsync.java | 2 +- .../my_vres/client/widgets/ClickableVRE.java | 4 +- .../my_vres/server/MyVREsServiceImpl.java | 153 ++++++++++-------- .../my_vres/server/portlet/MyVREsPortlet.java | 4 +- .../my_vres/shared/AuthorizationBean.java | 17 +- 10 files changed, 143 insertions(+), 86 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 7957cea..3ff7ea6 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -5,7 +5,7 @@ - + uses diff --git a/.tern-project b/.tern-project index a185ba0..61348cc 100644 --- a/.tern-project +++ b/.tern-project @@ -1 +1,17 @@ -{"ide":{"scriptPaths":[]},"plugins":{"aui":{},"liferay":{},"yui":{}},"libs":["ecma5","browser"]} \ No newline at end of file +{ + "plugins": { + "aui": { + + }, + "liferay": { + + }, + "yui": { + + } + }, + "libs": [ + "ecma5", + "browser" + ] +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index e38af73..a36d2d4 100644 --- a/pom.xml +++ b/pom.xml @@ -65,10 +65,29 @@ org.gcube.dvos usermanagement-core + + com.googlecode.json-simple + json-simple + 1.1.1 + compile + + + org.apache.httpcomponents + httpclient + 4.3 + compile + org.gcube.resources.discovery ic-client + provided + + + org.gcube.portal.auth + portal-auth-library + [1.0.0-SNAPSHOT,) + provided org.gcube.core diff --git a/src/main/java/org/gcube/portlet/user/my_vres/client/MyVREs.java b/src/main/java/org/gcube/portlet/user/my_vres/client/MyVREs.java index 951449e..5d1b194 100644 --- a/src/main/java/org/gcube/portlet/user/my_vres/client/MyVREs.java +++ b/src/main/java/org/gcube/portlet/user/my_vres/client/MyVREs.java @@ -18,11 +18,11 @@ import com.google.gwt.user.client.ui.RootPanel; public class MyVREs implements EntryPoint { public static final String GET_REDIRECTURI_PARAMETER = "redirect_uri"; public static final String GET_STATE_PARAMETER = "state"; - public static final String GET_CONTEXT_PARAMETER = "context"; + public static final String GET_CONTEXT_PARAMETER = "scope"; public static final String GET_CLIENT_ID_PARAMETER = "client_id"; public static final String GET_CLIENT_SECRET_PARAMETER = "client_secret"; - public static final String GET_AUTH_TOKEN_PARAMETER = "gcube-token"; + public static final String GET_AUTH_TOKEN_PARAMETER = "code"; private final MyVREsServiceAsync myVREsService = GWT.create(MyVREsService.class); @@ -49,11 +49,11 @@ public class MyVREs implements EntryPoint { RootPanel.get("myVREsDIV").add(new VresPanel(params)); } else { - myVREsService.getUserToken(params.context, params.state, params.clientId, params.redirectURI, new AsyncCallback() { + myVREsService.getUserQualifierToken(params.context, params.state, params.clientId, params.redirectURI, new AsyncCallback() { @Override public void onSuccess(AuthorizationBean result) { if (result.isSuccess()) { - Location.assign(params.redirectURI+"?"+GET_AUTH_TOKEN_PARAMETER+"="+result.getToken()+"&"+GET_STATE_PARAMETER+"="+result.getState()); + Location.assign(params.redirectURI+"?"+GET_AUTH_TOKEN_PARAMETER+"="+result.getOAuth2TemporaryCode()+"&"+GET_STATE_PARAMETER+"="+result.getState()); } else { HTML message = new HTML("There were issues in managing this request: " + result.getErrorDescription()); message.setStyleName("portlet-msg-error"); diff --git a/src/main/java/org/gcube/portlet/user/my_vres/client/MyVREsService.java b/src/main/java/org/gcube/portlet/user/my_vres/client/MyVREsService.java index 30d2023..305d427 100644 --- a/src/main/java/org/gcube/portlet/user/my_vres/client/MyVREsService.java +++ b/src/main/java/org/gcube/portlet/user/my_vres/client/MyVREsService.java @@ -18,5 +18,5 @@ public interface MyVREsService extends RemoteService { String getSiteLandingPagePath(); - AuthorizationBean getUserToken(String context, String state, String clientId, String authorisedRedirectURL); + AuthorizationBean getUserQualifierToken(String context, String state, String clientId, String authorisedRedirectURL); } diff --git a/src/main/java/org/gcube/portlet/user/my_vres/client/MyVREsServiceAsync.java b/src/main/java/org/gcube/portlet/user/my_vres/client/MyVREsServiceAsync.java index d4620ff..5122b9e 100644 --- a/src/main/java/org/gcube/portlet/user/my_vres/client/MyVREsServiceAsync.java +++ b/src/main/java/org/gcube/portlet/user/my_vres/client/MyVREsServiceAsync.java @@ -15,7 +15,7 @@ public interface MyVREsServiceAsync { void getSiteLandingPagePath(AsyncCallback callback); - void getUserToken(String context, String state, String clientId, String authorisedRedirectURI, + void getUserQualifierToken(String context, String state, String clientId, String authorisedRedirectURI, AsyncCallback callback); } diff --git a/src/main/java/org/gcube/portlet/user/my_vres/client/widgets/ClickableVRE.java b/src/main/java/org/gcube/portlet/user/my_vres/client/widgets/ClickableVRE.java index e3b0274..56fd1c5 100644 --- a/src/main/java/org/gcube/portlet/user/my_vres/client/widgets/ClickableVRE.java +++ b/src/main/java/org/gcube/portlet/user/my_vres/client/widgets/ClickableVRE.java @@ -62,11 +62,11 @@ public class ClickableVRE extends HTML { if (params != null) { addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { - myVREsService.getUserToken(vre.getContext(), params.getState(), params.getClientId(), params.getRedirectURI(), new AsyncCallback() { + myVREsService.getUserQualifierToken(vre.getContext(), params.getState(), params.getClientId(), params.getRedirectURI(), new AsyncCallback() { @Override public void onSuccess(AuthorizationBean result) { if (result.isSuccess()) { - Location.assign(params.getRedirectURI()+"?"+MyVREs.GET_AUTH_TOKEN_PARAMETER+"="+result.getToken()+"&"+MyVREs.GET_STATE_PARAMETER+"="+result.getState()); + Location.assign(params.getRedirectURI()+"?"+MyVREs.GET_AUTH_TOKEN_PARAMETER+"="+result.getOAuth2TemporaryCode()+"&"+MyVREs.GET_STATE_PARAMETER+"="+result.getState()); } else { HTML message = new HTML("There were issues in managing this request: " + result.getErrorDescription()); message.setStyleName("portlet-msg-error"); diff --git a/src/main/java/org/gcube/portlet/user/my_vres/server/MyVREsServiceImpl.java b/src/main/java/org/gcube/portlet/user/my_vres/server/MyVREsServiceImpl.java index a6fc37e..8fd530c 100644 --- a/src/main/java/org/gcube/portlet/user/my_vres/server/MyVREsServiceImpl.java +++ b/src/main/java/org/gcube/portlet/user/my_vres/server/MyVREsServiceImpl.java @@ -1,27 +1,29 @@ package org.gcube.portlet.user.my_vres.server; -import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; -import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; - import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; +import java.util.UUID; import javax.servlet.http.HttpServletRequest; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.params.HttpClientParams; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.LaxRedirectStrategy; import org.gcube.common.portal.GCubePortalConstants; import org.gcube.common.portal.PortalContext; import org.gcube.common.resources.gcore.ServiceEndpoint; -import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; -import org.gcube.common.resources.gcore.utils.Group; -import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.portal.auth.AuthUtil; import org.gcube.portlet.user.my_vres.client.MyVREsService; import org.gcube.portlet.user.my_vres.shared.AuthorizationBean; import org.gcube.portlet.user.my_vres.shared.UserBelonging; import org.gcube.portlet.user.my_vres.shared.VRE; -import org.gcube.resources.discovery.client.api.DiscoveryClient; -import org.gcube.resources.discovery.client.queries.api.SimpleQuery; import org.gcube.vomanagement.usermanagement.GroupManager; import org.gcube.vomanagement.usermanagement.exception.GroupRetrievalFault; import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException; @@ -32,6 +34,7 @@ import org.gcube.vomanagement.usermanagement.model.GCubeGroup; import org.gcube.vomanagement.usermanagement.model.GCubeUser; import org.gcube.vomanagement.usermanagement.model.VirtualGroup; import org.gcube.vomanagement.usermanagement.util.ManagementUtils; +import org.json.simple.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -260,16 +263,27 @@ public class MyVREsServiceImpl extends RemoteServiceServlet implements MyVREsSer } @Override - public AuthorizationBean getUserToken(String context, String state, String clientId, String redirectURL) { + public AuthorizationBean getUserQualifierToken(String context, String state, String clientId, String redirectURL) { + String infraName = PortalContext.getConfiguration().getInfrastructureName(); if (clientId == null || clientId.compareTo("")== 0) { return new AuthorizationBean(null, null, false, "client_id is null, you MUST register your application to allow users connect with their D4Science Credentials"); } if (redirectURL == null || redirectURL.compareTo("")== 0) { return new AuthorizationBean(null, null, false, "authorised redirect URL is null, you MUST pass the authorisedRedirectURI related to your client_id registered application to allow users connect with their D4Science Credentials"); } - List authorisedRedirectURLs = getAuthorisedRedirectURLsFromIs(clientId); + ServiceEndpoint authorisedApp = null; + try { + authorisedApp = AuthUtil.getAuthorisedApplicationInfoFromIsICClient(infraName, clientId); + } catch (Exception e1) { + e1.printStackTrace(); + return new AuthorizationBean(null, null, false, "Ops!, we failed to check if ("+ clientId + ") is a valid clientId, some error occurred, please try in a few minutes. If the problem persists please open an incident ticket"); + } + if (authorisedApp == null) { + return new AuthorizationBean(null, null, false, "Your application ("+ clientId + ") is not authorized in the infrastructure"); + } + List authorisedRedirectURLs = AuthUtil.getAuthorisedRedirectURLsFromIs(authorisedApp); if (authorisedRedirectURLs == null || authorisedRedirectURLs.isEmpty()) { - return new AuthorizationBean(null, null, false, "Your application ("+ clientId + ") is not registered or there are no authorised redirect URLs registered for your application"); + return new AuthorizationBean(null, null, false, "Your application ("+ clientId + ") have no authorised redirect URLs"); } boolean urlAuthorised = false; for (String authorisedURL : authorisedRedirectURLs) @@ -310,63 +324,70 @@ public class MyVREsServiceImpl extends RemoteServiceServlet implements MyVREsSer _log.error("Something wrong in retrieving the user"); return new AuthorizationBean(null, null, false, "Something wrong in retrieving the logged in user, is session expired?"); } - String token = pContext.getCurrentUserToken(context, username); - if (token == null) { - _log.error("Something wrong in retrieving the user token in this context: " + context + " username="+username); - return new AuthorizationBean(null, null, false, "Something wrong in retrieving the user token in this context: " + context + " username="+username); + //no errors, proceed to step 2 + String userToken = pContext.getCurrentUserToken(context, username); + String appName = authorisedApp.profile().name(); + String qToken = AuthUtil.generateAuthorizationQualifierToken(appName, userToken); + _log.info("Received qualifier token for useer " + username + "=" + qToken); + if (qToken == null) { + _log.error("Something wrong in retrieving the user qualifier token in this context: " + context + " username="+username); + return new AuthorizationBean(null, null, false, "Something wrong in retrieving the user qualifier token in this context: " + context + " username="+username); } - _log.debug("Authorisation OAUTH returning user token in this context: " + context + " username="+username); - return new AuthorizationBean(token, state, true, null); + String tempCode = UUID.randomUUID().toString(); + if (! authorizeApplication(infraName, qToken, tempCode, clientId, redirectURL)) { + _log.error("Something wrong in authorizing this application in this context: " + context ); + return new AuthorizationBean(null, null, false, "Something wrong in authorizing this application in this context: " + context + " an error occurred in the oAuth Service"); + } + + _log.debug("Authorisation OAUTH 2 OK returning temporary code in this context: " + context + " username="+username); + return new AuthorizationBean(tempCode, state, true, null); + } + /** + * we post to the auth service a temporary code to be used within seconds from the application + * @param qToken the user qualifier token + * @param tempCode the temporary code + * @param clientId tha app id + * @param redirectURI the authorised redirect URI + * @return + */ + @SuppressWarnings("unchecked") + private boolean authorizeApplication(String infrastructureName, String qToken, String tempCode, String clientId, String redirectURL) { + + String fullPath2oAuthService = null; + try { + fullPath2oAuthService = AuthUtil.getOAuthServiceEndPoint(infrastructureName) + + "/v2/push-authentication-code?gcube-token=" + qToken; + } catch (Exception e1) { + _log.error("failed to discover oauth service endpoint "); + return false; + } + fullPath2oAuthService = fullPath2oAuthService.replaceAll("http", "https"); + fullPath2oAuthService = fullPath2oAuthService.replaceAll("80", "443"); + + JSONObject object = new JSONObject(); + object.put("code", tempCode); + object.put("redirect_uri", redirectURL); + object.put("client_id", clientId); + + try (CloseableHttpClient httpClient = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build()) { + HttpPost httpPostRequest = new HttpPost(fullPath2oAuthService); + httpPostRequest.addHeader("Content-type", "application/json"); + StringEntity params = new StringEntity(object.toJSONString(), ContentType.APPLICATION_JSON); + httpPostRequest.setEntity(params); + HttpResponse response = httpClient.execute(httpPostRequest); + if (response.getStatusLine().getStatusCode() < 200 || response.getStatusLine().getStatusCode() >= 300) { + _log.error("failed to patch the product. response status line from " + + fullPath2oAuthService + " was: " + response.getStatusLine()); + return false; + } + + }catch(Exception e){ + _log.error("Failed to perform request", e); + } + + return true; } -//TODO: check the query, it doesn work - private List getPortalConfigurationFromIS(String infrastructureName, String clientId) throws Exception { - String scope = "/" + infrastructureName; - String currScope = ScopeProvider.instance.get(); - ScopeProvider.instance.set(scope); - SimpleQuery query = queryFor(ServiceEndpoint.class); - query.addCondition("$resource/Profile/Category/text() eq '"+ SERVICE_ENDPOINT_CATEGORY +"'"); - query.addCondition("$resource/Profile/Name/text() eq '"+ clientId +"'"); - DiscoveryClient client = clientFor(ServiceEndpoint.class); - List toReturn = client.submit(query); - ScopeProvider.instance.set(currScope); - return toReturn; - } - /** - * look for the clientId AccessEndpoint passes as parameter - * @param gatewayName - * @param clientId - * @return the client secret related to the id, or null if non existent - */ - private List getAuthorisedRedirectURLsFromIs(String clientId) { - PortalContext pContext = PortalContext.getConfiguration(); - String scope = "/"+pContext.getInfrastructureName(); - List autRedirectURLs = new ArrayList<>(); - try { - List list = getPortalConfigurationFromIS(pContext.getInfrastructureName(), clientId); - if (list.size() > 1) { - _log.error("Too many Service Endpoints having name " + clientId +" in this scope having Category " + SERVICE_ENDPOINT_CATEGORY); - } - else if (list.size() == 0){ - _log.warn("There is no Service Endpoint having name " + clientId +" and Category " + SERVICE_ENDPOINT_CATEGORY + " in this scope: " + scope); - } - else { - for (ServiceEndpoint res : list) { - Group apGroup = res.profile().accessPoints(); - AccessPoint[] accessPoints = (AccessPoint[]) apGroup.toArray(new AccessPoint[apGroup.size()]); - for (int i = 0; i < accessPoints.length; i++) { - if (accessPoints[i].name().compareTo(REDIRECT_URL) == 0) { - AccessPoint found = accessPoints[i]; - autRedirectURLs.add(found.address()); - } - } - } - } - } catch (Exception e) { - e.printStackTrace(); - return null; - } - return autRedirectURLs; - } + } \ No newline at end of file diff --git a/src/main/java/org/gcube/portlet/user/my_vres/server/portlet/MyVREsPortlet.java b/src/main/java/org/gcube/portlet/user/my_vres/server/portlet/MyVREsPortlet.java index b5a0033..d9eac5f 100644 --- a/src/main/java/org/gcube/portlet/user/my_vres/server/portlet/MyVREsPortlet.java +++ b/src/main/java/org/gcube/portlet/user/my_vres/server/portlet/MyVREsPortlet.java @@ -13,6 +13,8 @@ import javax.portlet.PortletRequestDispatcher; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; +import org.gcube.common.portal.PortalContext; + import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; @@ -36,7 +38,7 @@ public class MyVREsPortlet extends GenericPortlet { protected void include(String path, RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException { PortletRequestDispatcher portletRequestDispatcher = getPortletContext().getRequestDispatcher(path); - + PortalContext.setUserInSession(renderRequest); if (portletRequestDispatcher == null) { _log.error(path + " is not a valid include"); } diff --git a/src/main/java/org/gcube/portlet/user/my_vres/shared/AuthorizationBean.java b/src/main/java/org/gcube/portlet/user/my_vres/shared/AuthorizationBean.java index 9a0c20a..24fb1b8 100644 --- a/src/main/java/org/gcube/portlet/user/my_vres/shared/AuthorizationBean.java +++ b/src/main/java/org/gcube/portlet/user/my_vres/shared/AuthorizationBean.java @@ -4,30 +4,29 @@ import java.io.Serializable; @SuppressWarnings("serial") public class AuthorizationBean implements Serializable { - private String token; + private String oAuth2TemporaryCode; private String state; private boolean success; private String errorDescription; public AuthorizationBean() { super(); - // TODO Auto-generated constructor stub } - public AuthorizationBean(String token, String state, boolean success, String errorDescription) { + public AuthorizationBean(String oAuth2TemporaryCode, String state, boolean success, String errorDescription) { super(); - this.token = token; + this.oAuth2TemporaryCode = oAuth2TemporaryCode; this.state = state; this.success = success; this.errorDescription = errorDescription; } - public String getToken() { - return token; + public String getOAuth2TemporaryCode() { + return oAuth2TemporaryCode; } - public void setToken(String token) { - this.token = token; + public void seOAuth2TemporaryCode(String oAuth2TemporaryCode) { + this.oAuth2TemporaryCode = oAuth2TemporaryCode; } public String getState() { @@ -56,7 +55,7 @@ public class AuthorizationBean implements Serializable { @Override public String toString() { - return "AuthorizationBean [token=" + token + ", state=" + state + ", success=" + success + ", errorDescription=" + return "AuthorizationBean [oAuth2TemporaryCode=" + oAuth2TemporaryCode + ", state=" + state + ", success=" + success + ", errorDescription=" + errorDescription + "]"; }