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:
parent
5623845caa
commit
807cea8e60
|
@ -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>
|
||||||
|
|
|
@ -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
51
pom.xml
|
@ -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>
|
||||||
|
|
|
@ -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){
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue