2016-10-18 23:31:04 +02:00
package org.gcube.data_catalogue.grsf_publish_ws.filters ;
import static org.gcube.common.authorization.client.Constants.authorizationService ;
import java.io.IOException ;
2016-10-26 18:40:10 +02:00
import java.io.InputStream ;
2016-10-18 23:31:04 +02:00
import javax.ws.rs.container.ContainerRequestContext ;
import javax.ws.rs.container.ContainerRequestFilter ;
2016-10-26 10:12:47 +02:00
import javax.ws.rs.core.Context ;
2016-10-19 14:34:19 +02:00
import javax.ws.rs.core.MediaType ;
2016-10-18 23:31:04 +02:00
import javax.ws.rs.core.MultivaluedMap ;
import javax.ws.rs.core.Response ;
2016-10-26 10:12:47 +02:00
import javax.ws.rs.core.UriInfo ;
2016-10-18 23:31:04 +02:00
import javax.ws.rs.ext.Provider ;
import org.gcube.common.authorization.library.AuthorizationEntry ;
import org.gcube.common.authorization.library.provider.AuthorizationProvider ;
2016-11-04 16:26:19 +01:00
import org.gcube.common.authorization.library.provider.SecurityTokenProvider ;
2016-10-18 23:31:04 +02:00
import org.gcube.common.authorization.library.utils.Caller ;
2016-10-19 09:57:31 +02:00
import org.gcube.common.portal.PortalContext ;
2016-10-18 23:31:04 +02:00
import org.gcube.common.scope.api.ScopeProvider ;
2016-10-19 14:34:19 +02:00
import org.gcube.data_catalogue.grsf_publish_ws.json.output.ResponseBean ;
2016-10-18 23:31:04 +02:00
import org.slf4j.LoggerFactory ;
2016-10-26 18:40:10 +02:00
import com.google.common.base.Charsets ;
import eu.trentorise.opendata.traceprov.internal.org.apache.commons.io.IOUtils ;
2016-10-18 23:31:04 +02:00
/ * *
* Requests filter : is invoked before any request reaches a service method
* @author Costantino Perciante at ISTI - CNR
* /
@Provider
2016-10-19 14:26:26 +02:00
public class RequestsAuthAccountingFilter implements ContainerRequestFilter {
2016-10-18 23:31:04 +02:00
2016-10-19 14:26:26 +02:00
private static final org . slf4j . Logger logger = LoggerFactory . getLogger ( RequestsAuthAccountingFilter . class ) ;
2016-10-18 23:31:04 +02:00
private static final String AUTH_TOKEN = " gcube-token " ;
2016-10-26 18:40:10 +02:00
2016-10-26 10:12:47 +02:00
@Context UriInfo info ;
2016-10-19 14:26:26 +02:00
2016-10-18 23:31:04 +02:00
@Override
public void filter ( ContainerRequestContext requestContext )
throws IOException {
logger . info ( " Intercepted request, checking if it contains authorization token " ) ;
2016-10-26 10:12:47 +02:00
String pathRequest = info . getAbsolutePath ( ) . toString ( ) ;
2016-10-26 18:40:10 +02:00
2016-10-26 10:12:47 +02:00
if ( pathRequest . contains ( " hello " ) | | pathRequest . endsWith ( " rest/ " ) )
return ;
2016-10-18 23:31:04 +02:00
2016-10-26 18:40:10 +02:00
try {
if ( isJson ( requestContext ) ) {
2016-11-06 21:21:11 +01:00
// read it
2016-10-26 18:40:10 +02:00
String json = IOUtils . toString ( requestContext . getEntityStream ( ) , Charsets . UTF_8 ) ;
// replace input stream for Jersey as we've already read it
InputStream in = IOUtils . toInputStream ( json ) ;
logger . debug ( " JSON REQUEST IS " + json ) ;
requestContext . setEntityStream ( in ) ;
}
} catch ( Exception ex ) {
logger . error ( " JSON IS MISSING " , ex ) ;
}
2016-10-18 23:31:04 +02:00
// check if the request contains gcube-token
String tokenInHeader = null , tokenAsQueryParameter = null ;
MultivaluedMap < String , String > headers = requestContext . getHeaders ( ) ;
if ( headers ! = null & & headers . containsKey ( AUTH_TOKEN ) )
tokenInHeader = headers . get ( AUTH_TOKEN ) . get ( 0 ) ;
MultivaluedMap < String , String > queryParameters = requestContext . getUriInfo ( ) . getQueryParameters ( ) ;
if ( queryParameters ! = null & & queryParameters . containsKey ( AUTH_TOKEN ) )
tokenAsQueryParameter = queryParameters . get ( AUTH_TOKEN ) . get ( 0 ) ;
if ( tokenInHeader ! = null ) {
logger . info ( " Token in " + tokenInHeader . substring ( 0 , 5 ) + " ******************** " ) ;
AuthorizationEntry ae = validateToken ( tokenInHeader ) ;
if ( ae ! = null ) {
2016-11-06 21:21:11 +01:00
setTokenInThread ( ae , tokenInHeader ) ;
2016-10-18 23:31:04 +02:00
} else
2016-10-19 14:34:19 +02:00
requestContext . abortWith ( Response . status ( Response . Status . UNAUTHORIZED ) . type ( MediaType . APPLICATION_JSON ) . entity ( new ResponseBean ( false , " Invalid or missing gcube-token " , null ) ) . build ( ) ) ;
2016-10-18 23:31:04 +02:00
} else if ( tokenAsQueryParameter ! = null ) {
logger . info ( " Token is " + tokenAsQueryParameter . substring ( 0 , 5 ) + " ******************** " ) ;
AuthorizationEntry ae = validateToken ( tokenAsQueryParameter ) ;
if ( ae ! = null ) {
2016-11-06 21:21:11 +01:00
setTokenInThread ( ae , tokenAsQueryParameter ) ;
2016-10-18 23:31:04 +02:00
} else
2016-10-19 14:34:19 +02:00
requestContext . abortWith ( Response . status ( Response . Status . UNAUTHORIZED ) . type ( MediaType . APPLICATION_JSON ) . entity ( new ResponseBean ( false , " Invalid or missing gcube-token " , null ) ) . build ( ) ) ;
2016-10-18 23:31:04 +02:00
}
else
2016-10-19 14:34:19 +02:00
requestContext . abortWith ( Response . status ( Response . Status . UNAUTHORIZED ) . type ( MediaType . APPLICATION_JSON ) . entity ( new ResponseBean ( false , " Invalid or missing gcube-token " , null ) ) . build ( ) ) ;
2016-10-18 23:31:04 +02:00
}
2016-11-06 21:21:11 +01:00
/ * *
* Set token and scope in thread .
* @param ae
* @param token
* /
private static void setTokenInThread ( AuthorizationEntry ae , String token ) {
logger . debug ( " Setting scope " + ae . getContext ( ) ) ;
AuthorizationProvider . instance . set ( new Caller ( ae . getClientInfo ( ) , ae . getQualifier ( ) ) ) ;
ScopeProvider . instance . set ( ae . getContext ( ) ) ;
SecurityTokenProvider . instance . set ( token ) ;
logger . info ( " Authorization entry set in thread local " ) ;
return ;
}
2016-10-18 23:31:04 +02:00
/ * *
* Validate token .
* @param token
* @return null if validation fails
* /
private static AuthorizationEntry validateToken ( String token ) {
AuthorizationEntry res = null ;
try {
2016-10-19 09:57:31 +02:00
// set the root scope
ScopeProvider . instance . set ( " / " + PortalContext . getConfiguration ( ) . getInfrastructureName ( ) ) ;
2016-10-18 23:31:04 +02:00
logger . debug ( " Validating token " + token ) ;
res = authorizationService ( ) . get ( token ) ;
logger . debug ( " Token seems valid for scope " + res . getContext ( ) + " and user " + res . getClientInfo ( ) . getId ( ) ) ;
} catch ( Exception e ) {
logger . error ( " The token is not valid. This request will be rejected!!! ( " + token + " ) " , e ) ;
2016-10-19 09:57:31 +02:00
} finally {
ScopeProvider . instance . reset ( ) ;
2016-10-18 23:31:04 +02:00
}
return res ;
}
2016-11-06 21:21:11 +01:00
/ * *
* Check the request is of type application / json
* @param request
* @return
* /
2016-10-26 18:40:10 +02:00
boolean isJson ( ContainerRequestContext request ) {
// define rules when to read body
2016-11-04 16:26:19 +01:00
return request . getMediaType ( ) . toString ( ) . contains ( MediaType . APPLICATION_JSON ) ;
2016-10-26 18:40:10 +02:00
}
2016-10-18 23:31:04 +02:00
}