grsf-publisher-ws/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/filters/RequestsAuthAccountingFilte...

145 lines
5.2 KiB
Java

package org.gcube.data_catalogue.grsf_publish_ws.filters;
import static org.gcube.common.authorization.client.Constants.authorizationService;
import java.io.IOException;
import java.io.InputStream;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Provider;
import org.gcube.common.authorization.library.AuthorizationEntry;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.portal.PortalContext;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.data_catalogue.grsf_publish_ws.json.output.ResponseBean;
import org.slf4j.LoggerFactory;
import com.google.common.base.Charsets;
import eu.trentorise.opendata.traceprov.internal.org.apache.commons.io.IOUtils;
/**
* Requests filter: is invoked before any request reaches a service method
* @author Costantino Perciante at ISTI-CNR
*/
@Provider
public class RequestsAuthAccountingFilter implements ContainerRequestFilter{
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(RequestsAuthAccountingFilter.class);
private static final String AUTH_TOKEN = "gcube-token";
@Context UriInfo info;
@Override
public void filter(ContainerRequestContext requestContext)
throws IOException {
logger.info("Intercepted request, checking if it contains authorization token");
String pathRequest = info.getAbsolutePath().toString();
if(pathRequest.contains("hello") || pathRequest.endsWith("rest/"))
return;
try {
if (isJson(requestContext)) {
// read it
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);
}
// 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){
setTokenInThread(ae, tokenInHeader);
}else
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).type(MediaType.APPLICATION_JSON).entity(new ResponseBean(false, "Invalid or missing gcube-token", null)).build());
}else if(tokenAsQueryParameter != null){
logger.info("Token is " + tokenAsQueryParameter.substring(0, 5) + "********************");
AuthorizationEntry ae = validateToken(tokenAsQueryParameter);
if(ae != null){
setTokenInThread(ae, tokenAsQueryParameter);
}else
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).type(MediaType.APPLICATION_JSON).entity(new ResponseBean(false, "Invalid or missing gcube-token", null)).build());
}
else
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).type(MediaType.APPLICATION_JSON).entity(new ResponseBean(false, "Invalid or missing gcube-token", null)).build());
}
/**
* 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;
}
/**
* Validate token.
* @param token
* @return null if validation fails
*/
private static AuthorizationEntry validateToken(String token){
AuthorizationEntry res = null;
try {
// set the root scope
ScopeProvider.instance.set("/" + PortalContext.getConfiguration().getInfrastructureName());
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);
}finally{
ScopeProvider.instance.reset();
}
return res;
}
/**
* Check the request is of type application/json
* @param request
* @return
*/
boolean isJson(ContainerRequestContext request) {
// define rules when to read body
return request.getMediaType().toString().contains(MediaType.APPLICATION_JSON);
}
}