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
This commit is contained in:
costantino.perciante 2017-01-29 17:11:55 +00:00
parent 5623845caa
commit 807cea8e60
8 changed files with 143 additions and 38 deletions

View File

@ -5,6 +5,6 @@
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<property name="java-output-path" value="/oauth/target/classes"/> <property name="java-output-path" value="/oauth/target/classes"/>
<property name="context-root" value="oauth_gCube_App"/> <property name="context-root" value="gcube-oauth"/>
</wb-module> </wb-module>
</project-modules> </project-modules>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<faceted-project> <faceted-project>
<fixed facet="wst.jsdt.web"/> <fixed facet="wst.jsdt.web"/>
<installed facet="jst.web" version="2.3"/> <installed facet="jst.web" version="3.0"/>
<installed facet="wst.jsdt.web" version="1.0"/> <installed facet="wst.jsdt.web" version="1.0"/>
<installed facet="java" version="1.7"/> <installed facet="java" version="1.7"/>
<installed facet="jst.jaxrs" version="2.0"/> <installed facet="jst.jaxrs" version="2.0"/>

51
pom.xml
View File

@ -13,9 +13,9 @@
<artifactId>oauth</artifactId> <artifactId>oauth</artifactId>
<packaging>war</packaging> <packaging>war</packaging>
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
<name>oauth gCube App</name> <name>gcube-oauth</name>
<properties> <properties>
<java-version>1.7</java-version> <java-version>1.7</java-version>
<version.jersey>2.22.1</version.jersey> <version.jersey>2.22.1</version.jersey>
<distroDirectory>${project.basedir}/distro</distroDirectory> <distroDirectory>${project.basedir}/distro</distroDirectory>
@ -44,23 +44,6 @@
</dependencyManagement> </dependencyManagement>
<dependencies> <dependencies>
<!-- SmartGears -->
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-smartgears</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-smartgears-app</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>org.glassfish.jersey.containers</groupId> <groupId>org.glassfish.jersey.containers</groupId>
<!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core" --> <!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core" -->
@ -87,10 +70,27 @@
<artifactId>jersey-media-sse</artifactId> <artifactId>jersey-media-sse</artifactId>
<version>${version.jersey}</version> <version>${version.jersey}</version>
</dependency> </dependency>
<!-- <dependency> -->
<!-- <groupId>org.glassfish.jersey.ext</groupId> -->
<!-- <artifactId>jersey-bean-validation</artifactId> -->
<!-- <version>${version.jersey}</version> -->
<!-- </dependency> -->
<dependency> <dependency>
<groupId>org.glassfish.jersey.ext</groupId> <groupId>javax.servlet</groupId>
<artifactId>jersey-bean-validation</artifactId> <artifactId>servlet-api</artifactId>
<version>${version.jersey}</version> <version>3.0-alpha-1</version>
<scope>compile</scope>
</dependency>
<!-- SmartGears -->
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-smartgears</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-smartgears-app</artifactId>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
@ -98,6 +98,11 @@
<version>3.8.1</version> <version>3.8.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<finalName>${name}</finalName> <finalName>${name}</finalName>

View File

@ -8,6 +8,7 @@ import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam; import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
@ -28,22 +29,27 @@ import org.gcube.portal.oauth.output.AccessTokenErrorResponse;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@Path("v2/") @Path("/v2")
@Singleton @Singleton
public class OauthService { 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); private static final org.slf4j.Logger logger = LoggerFactory.getLogger(OauthService.class);
/** /**
* This map contains couples <code, {qualifier-token, insert time}> * This map contains couples <code, {qualifier-token, insert time}>
*/ */
private Map<String, CacheBean> entries = new ConcurrentHashMap<String, CacheBean>(); private Map<String, CacheBean> entries;
/** /**
* Since this is a singleton sub-service, there will be just one call to this constructor and one running thread * 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. * to clean up expired codes.
*/ */
public OauthService() { public OauthService() {
logger.info("Singleton gcube-oauth service built.");
entries = new ConcurrentHashMap<String, CacheBean>();
CacheCleaner cleaner = new CacheCleaner(entries); CacheCleaner cleaner = new CacheCleaner(entries);
cleaner.start(); cleaner.start();
} }
@ -67,6 +73,13 @@ public class OauthService {
private boolean checkIsapplicationTokenType(ClientType clientType){ private boolean checkIsapplicationTokenType(ClientType clientType){
return clientType.equals(ClientType.EXTERNALSERVICE); return clientType.equals(ClientType.EXTERNALSERVICE);
} }
@GET
@Path("check")
@Produces(MediaType.TEXT_PLAIN)
public Response checkService(){
return Response.status(Status.OK).entity("Ready!").build();
}
@POST @POST
@ -101,7 +114,7 @@ public class OauthService {
@POST @POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON) @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. * 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 * @param requestInJson
@ -122,7 +135,8 @@ public class OauthService {
Status status = Status.BAD_REQUEST; Status status = Status.BAD_REQUEST;
logger.info("Request to exchange code for token"); 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{ try{
// check if something is missing // check if something is missing
@ -167,7 +181,7 @@ public class OauthService {
CacheBean entry = entries.get(code); CacheBean entry = entries.get(code);
if(!entry.getRedirectUri().equals(redirectUri) || !entry.getClientId().equals(clientId)) if(!entry.getRedirectUri().equals(redirectUri) || !entry.getClientId().equals(clientId))
return "invalid_grant"; return "invalid_grant";
if(!grantType.equals("authorization_code")) if(!grantType.equals(GRANT_TYPE_VALUE))
return "unsupported_grant_type"; return "unsupported_grant_type";
return null; return null;
}catch(Exception e){ }catch(Exception e){

View File

@ -9,17 +9,21 @@ import com.fasterxml.jackson.annotation.JsonProperty;
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/ */
public class AccessTokenErrorResponse { public class AccessTokenErrorResponse {
@NotNull @NotNull
@JsonProperty("error") @JsonProperty("error")
private String error; private String error;
@JsonProperty("error_description") @JsonProperty("error_description")
private String errorDescription; private String errorDescription;
@JsonProperty("error_uri") @JsonProperty("error_uri")
private String errorUri; private String errorUri;
public AccessTokenErrorResponse() {
super();
}
/** /**
* @param error * @param error
* @param errorDescription * @param errorDescription

View File

@ -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<String, String> 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");
}
}
}
}

View File

@ -0,0 +1,8 @@
<application mode='online'>
<name>oauth</name>
<group>Portal</group>
<version>1.0.0-SNAPSHOT</version>
<description>gCube OAUTH Service</description>
<local-persistence location='target' />
<exclude>/v2/check</exclude>
</application>

View File

@ -1,7 +1,25 @@
<!DOCTYPE web-app PUBLIC <?xml version="1.0" encoding="UTF-8"?>
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
"http://java.sun.com/dtd/web-app_2_3.dtd" > xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<web-app> <display-name>RESTFul Web Service - OAUTH</display-name>
<display-name>Archetype Created Web Application</display-name> <servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>org.gcube.portal.oauth,org.gcube.portal.oauth.filter</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app> </web-app>