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 headers = requestContext.getHeaders(); if( headers != null && headers.containsKey(AUTH_TOKEN)) tokenInHeader = headers.get(AUTH_TOKEN).get(0); MultivaluedMap 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); } }