001/*
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 */
006package org.fcrepo.auth.common;
007
008import static org.slf4j.LoggerFactory.getLogger;
009
010import java.io.IOException;
011import java.security.Principal;
012import java.util.HashSet;
013import java.util.Set;
014
015import javax.servlet.Filter;
016import javax.servlet.FilterChain;
017import javax.servlet.FilterConfig;
018import javax.servlet.ServletException;
019import javax.servlet.ServletRequest;
020import javax.servlet.ServletResponse;
021import javax.servlet.http.HttpServletRequest;
022
023import org.apache.shiro.SecurityUtils;
024import org.apache.shiro.subject.Subject;
025import org.slf4j.Logger;
026
027/**
028 * @author peichman
029 */
030public class ServletContainerAuthFilter implements Filter {
031
032    private static final Logger log = getLogger(ServletContainerAuthFilter.class);
033
034    /**
035     * User role for Fedora's admin users
036     */
037    public static final String FEDORA_ADMIN_ROLE = "fedoraAdmin";
038
039    /**
040     * User role for Fedora's ordinary users
041     */
042    public static final String FEDORA_USER_ROLE = "fedoraUser";
043
044    // TODO: configurable set of role names: https://jira.duraspace.org/browse/FCREPO-2770
045    private static final String[] ROLE_NAMES = { FEDORA_ADMIN_ROLE, FEDORA_USER_ROLE };
046
047    @Override
048    public void init(final FilterConfig filterConfig) {
049        // this method intentionally left empty
050    }
051
052    @Override
053    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
054            throws IOException, ServletException {
055        final HttpServletRequest httpRequest = (HttpServletRequest) request;
056        final Principal servletUser = httpRequest.getUserPrincipal();
057        final Subject currentUser = SecurityUtils.getSubject();
058
059        if (servletUser != null) {
060            log.debug("There is a servlet user: {}", servletUser.getName());
061            final Set<String> roles = new HashSet<>();
062            for (final String roleName : ROLE_NAMES) {
063                log.debug("Testing role {}", roleName);
064                if (httpRequest.isUserInRole(roleName)) {
065                    log.debug("Servlet user {} has servlet role: {}", servletUser.getName(), roleName);
066                    roles.add(roleName);
067                }
068            }
069            final ContainerAuthToken token = new ContainerAuthToken(servletUser.getName(), roles);
070            log.debug("Credentials for servletUser = {}", token.getCredentials());
071            currentUser.login(token);
072        } else {
073            log.debug("Anonymous request");
074            // ensure the user is actually logged out
075            currentUser.logout();
076        }
077        chain.doFilter(request, response);
078    }
079
080    @Override
081    public void destroy() {
082        // this method intentionally left empty
083    }
084
085}