/** * The contents of this file are subject to the license and copyright * detailed in the LICENSE file at the root of the source * tree and available online at * * https://github.com/keeps/roda */ package org.roda.wui.filter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.roda.core.common.UserUtility; import org.roda.core.data.common.RodaConstants; import org.roda.core.data.exceptions.AuthenticationDeniedException; import org.roda.core.data.exceptions.GenericException; import org.roda.core.data.v2.common.Pair; import org.roda.core.data.v2.user.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Internal authentication filter for API requests. */ public class InternalApiAuthFilter implements Filter { /** Logger. */ private static final Logger LOGGER = LoggerFactory.getLogger(InternalApiAuthFilter.class); /** Paths excluded from being filtered. */ private List<String> exclusions = new ArrayList<>(); /** Authentication realm. */ private String realm = ""; @Override public void init(final FilterConfig filterConfig) throws ServletException { final String realmParam = filterConfig.getInitParameter("realm"); if (StringUtils.isNotBlank(realmParam)) { realm = realmParam; } final String exclusionsParam = filterConfig.getInitParameter("exclusions"); if (StringUtils.isNotBlank(exclusionsParam)) { final String[] listOfExclusions = exclusionsParam.split(","); for (String exclusion : listOfExclusions) { exclusions.add(exclusion.trim()); } } } @Override public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain chain) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) servletRequest; final HttpServletResponse response = (HttpServletResponse) servletResponse; if (!isRequestUrlExcluded(request) && request.getSession().getAttribute(UserUtility.RODA_USER) == null) { // No user yet try { UserUtility.setUser(request, getBasicAuthUser(request)); chain.doFilter(servletRequest, servletResponse); } catch (final AuthenticationDeniedException | GenericException e) { LOGGER.debug(e.getMessage(), e); response.setHeader(RodaConstants.HTTP_HEADERS_WWW_AUTHENTICATE, "Basic realm=\"" + realm + "\""); response.sendError(HttpServletResponse.SC_UNAUTHORIZED); } } else { chain.doFilter(servletRequest, servletResponse); } } /** * Return a {@link User} from the HTTP Basic auth header information. * * @param request * the HTTP request. * @return the {@link User}. * @throws AuthenticationDeniedException * if the credentials are invalid. * @throws GenericException * if some other error occurs. */ private User getBasicAuthUser(final HttpServletRequest request) throws AuthenticationDeniedException, GenericException { final Pair<String, String> credentials = new BasicAuthRequestWrapper(request).getCredentials(); if (credentials == null) { throw new AuthenticationDeniedException("No credentials!"); } else { final User user = UserUtility.getLdapUtility().getAuthenticatedUser(credentials.getFirst(), credentials.getSecond()); user.setIpAddress(request.getRemoteAddr()); return user; } } /** * Is the requested path in the list of exclusions? * * @param request * the request. * * @return <code>true</code> if it is excluded and <code>false</code> * otherwise. */ private boolean isRequestUrlExcluded(final HttpServletRequest request) { for (String exclusion : this.exclusions) { if (request.getPathInfo().matches(exclusion)) { return true; } } return false; } @Override public void destroy() { // do nothing } }