From 807cea8e6038ca67e00868f814eb0b15c5762007 Mon Sep 17 00:00:00 2001 From: "costantino.perciante" Date: Sun, 29 Jan 2017 17:11:55 +0000 Subject: [PATCH] Added filter to extract formparams before the access-token method is called. Unfortunately it is called after the smartgears' one, and the priority property doesn't work. Dependencies fixed in pom.xml git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portal/oauth@141889 82a268e6-3cf1-43bd-a215-b396298e98cf --- .settings/org.eclipse.wst.common.component | 2 +- ....eclipse.wst.common.project.facet.core.xml | 2 +- pom.xml | 51 +++++++++-------- .../org/gcube/portal/oauth/OauthService.java | 24 ++++++-- .../output/AccessTokenErrorResponse.java | 10 +++- .../oauth/request/filter/OauthFilter.java | 56 +++++++++++++++++++ src/main/webapp/WEB-INF/gcube-app.xml | 8 +++ src/main/webapp/WEB-INF/web.xml | 28 ++++++++-- 8 files changed, 143 insertions(+), 38 deletions(-) create mode 100644 src/main/java/org/gcube/portal/oauth/request/filter/OauthFilter.java create mode 100644 src/main/webapp/WEB-INF/gcube-app.xml diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 09dd0d8..0543109 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -5,6 +5,6 @@ - + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml index fffd28a..f7f0893 100644 --- a/.settings/org.eclipse.wst.common.project.facet.core.xml +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -1,7 +1,7 @@ - + diff --git a/pom.xml b/pom.xml index 50447cf..8b23d70 100644 --- a/pom.xml +++ b/pom.xml @@ -13,9 +13,9 @@ oauth war 1.0.0-SNAPSHOT - oauth gCube App - - + gcube-oauth + + 1.7 2.22.1 ${project.basedir}/distro @@ -44,23 +44,6 @@ - - - org.gcube.core - common-smartgears - provided - - - org.gcube.core - common-smartgears-app - compile - - - javax.servlet - servlet-api - 3.0-alpha-1 - compile - org.glassfish.jersey.containers @@ -87,10 +70,27 @@ jersey-media-sse ${version.jersey} + + + + + - org.glassfish.jersey.ext - jersey-bean-validation - ${version.jersey} + javax.servlet + servlet-api + 3.0-alpha-1 + compile + + + + org.gcube.core + common-smartgears + provided + + + org.gcube.core + common-smartgears-app + compile junit @@ -98,6 +98,11 @@ 3.8.1 test + + org.apache.commons + commons-io + 1.3.2 + ${name} diff --git a/src/main/java/org/gcube/portal/oauth/OauthService.java b/src/main/java/org/gcube/portal/oauth/OauthService.java index c53e634..68cd8a2 100644 --- a/src/main/java/org/gcube/portal/oauth/OauthService.java +++ b/src/main/java/org/gcube/portal/oauth/OauthService.java @@ -8,6 +8,7 @@ import java.util.concurrent.ConcurrentHashMap; import javax.inject.Singleton; import javax.ws.rs.Consumes; import javax.ws.rs.FormParam; +import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; @@ -28,22 +29,27 @@ import org.gcube.portal.oauth.output.AccessTokenErrorResponse; import org.slf4j.LoggerFactory; -@Path("v2/") +@Path("/v2") @Singleton public class OauthService { + public static final String OAUTH_TOKEN_GET_METHOD_NAME_REQUEST = "access-token"; + private static final String GRANT_TYPE_VALUE = "authorization_code"; + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(OauthService.class); /** * This map contains couples */ - private Map entries = new ConcurrentHashMap(); + private Map entries; /** * Since this is a singleton sub-service, there will be just one call to this constructor and one running thread * to clean up expired codes. */ public OauthService() { + logger.info("Singleton gcube-oauth service built."); + entries = new ConcurrentHashMap(); CacheCleaner cleaner = new CacheCleaner(entries); cleaner.start(); } @@ -67,6 +73,13 @@ public class OauthService { private boolean checkIsapplicationTokenType(ClientType clientType){ return clientType.equals(ClientType.EXTERNALSERVICE); } + + @GET + @Path("check") + @Produces(MediaType.TEXT_PLAIN) + public Response checkService(){ + return Response.status(Status.OK).entity("Ready!").build(); + } @POST @@ -101,7 +114,7 @@ public class OauthService { @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Produces(MediaType.APPLICATION_JSON) - @Path("access-token") + @Path(OAUTH_TOKEN_GET_METHOD_NAME_REQUEST) /** * The method should accept input values or in a json object or as FormParam. The request is validated here and not from SmartGears. * @param requestInJson @@ -122,7 +135,8 @@ public class OauthService { Status status = Status.BAD_REQUEST; logger.info("Request to exchange code for token"); - logger.info("Params are + client_id = " + clientId + ", client_secret = " + clientSecret.substring(0, 10) + ", redirect_uri = " +redirectUri + ", code = " + code.substring(0, 10)); + logger.info("Params are client_id = " + clientId + ", client_secret = " + clientSecret.substring(0, 10) + + "*******************"+ ", redirect_uri = " +redirectUri + ", code = " + code.substring(0, 10) + "*******************" + ", grant_type = " + grantType); try{ // check if something is missing @@ -167,7 +181,7 @@ public class OauthService { CacheBean entry = entries.get(code); if(!entry.getRedirectUri().equals(redirectUri) || !entry.getClientId().equals(clientId)) return "invalid_grant"; - if(!grantType.equals("authorization_code")) + if(!grantType.equals(GRANT_TYPE_VALUE)) return "unsupported_grant_type"; return null; }catch(Exception e){ diff --git a/src/main/java/org/gcube/portal/oauth/output/AccessTokenErrorResponse.java b/src/main/java/org/gcube/portal/oauth/output/AccessTokenErrorResponse.java index afd60da..fc4e621 100644 --- a/src/main/java/org/gcube/portal/oauth/output/AccessTokenErrorResponse.java +++ b/src/main/java/org/gcube/portal/oauth/output/AccessTokenErrorResponse.java @@ -9,17 +9,21 @@ import com.fasterxml.jackson.annotation.JsonProperty; * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) */ public class AccessTokenErrorResponse { - + @NotNull @JsonProperty("error") private String error; - + @JsonProperty("error_description") private String errorDescription; - + @JsonProperty("error_uri") private String errorUri; + public AccessTokenErrorResponse() { + super(); + } + /** * @param error * @param errorDescription diff --git a/src/main/java/org/gcube/portal/oauth/request/filter/OauthFilter.java b/src/main/java/org/gcube/portal/oauth/request/filter/OauthFilter.java new file mode 100644 index 0000000..8466ab3 --- /dev/null +++ b/src/main/java/org/gcube/portal/oauth/request/filter/OauthFilter.java @@ -0,0 +1,56 @@ +package org.gcube.portal.oauth.request.filter; + +import java.io.IOException; + +import javax.annotation.Priority; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Form; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriInfo; +import javax.ws.rs.ext.Provider; + +import org.gcube.portal.oauth.OauthService; +import org.glassfish.jersey.server.internal.InternalServerProperties; +import org.slf4j.LoggerFactory; + +/** + * This filter is used to manage request directed to the method "access-token". + * It maps the "security_code" of the request into the gcube-token and then redirect this call + * to the SmartGears's filters. Please note that FormParams are put by previous filters under + * a property named InternalServerProperties.FORM_DECODED_PROPERTY. + */ +@Provider +@Priority(value = 0) // it should be the highest (so that it is called before the smartgears'one) +public class OauthFilter implements ContainerRequestFilter{ + + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(OauthFilter.class); + + @Context UriInfo info; + + @Override + public void filter(ContainerRequestContext requestContext) + throws IOException { + + logger.debug("Filter oauth called, checking the called method"); + logger.debug("Request method type is " + requestContext.getMethod()); + String pathRequest = info.getAbsolutePath().toString(); + logger.debug("Requested method url is " + info.getAbsolutePath()); + + if(pathRequest.endsWith(OauthService.OAUTH_TOKEN_GET_METHOD_NAME_REQUEST)){ + + Form propertiesForm = (Form)requestContext.getProperty(InternalServerProperties.FORM_DECODED_PROPERTY); + MultivaluedMap map = propertiesForm.asMap(); + logger.debug("Request form parameters are " + map); + + if(map.containsKey("client_secret")){ + requestContext.getHeaders().add("gcube-token", map.get("client_secret").get(0)); + }else{ + logger.error("Parameter client_secret is missing"); + } + } + } +} + + diff --git a/src/main/webapp/WEB-INF/gcube-app.xml b/src/main/webapp/WEB-INF/gcube-app.xml new file mode 100644 index 0000000..a7f7393 --- /dev/null +++ b/src/main/webapp/WEB-INF/gcube-app.xml @@ -0,0 +1,8 @@ + + oauth + Portal + 1.0.0-SNAPSHOT + gCube OAUTH Service + + /v2/check + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 9f88c1f..4f7d83c 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -1,7 +1,25 @@ - + + - - Archetype Created Web Application +RESTFul Web Service - OAUTH + + jersey-servlet + org.glassfish.jersey.servlet.ServletContainer + + jersey.config.server.provider.packages + org.gcube.portal.oauth,org.gcube.portal.oauth.filter + + 1 + + + jersey-servlet + /* + + + index.jsp + +