001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.auth.common;
019
020import static org.slf4j.LoggerFactory.getLogger;
021
022import java.io.IOException;
023import java.security.Principal;
024import java.util.HashSet;
025import java.util.Set;
026
027import javax.servlet.Filter;
028import javax.servlet.FilterChain;
029import javax.servlet.FilterConfig;
030import javax.servlet.ServletException;
031import javax.servlet.ServletRequest;
032import javax.servlet.ServletResponse;
033import javax.servlet.http.HttpServletRequest;
034
035import org.apache.shiro.SecurityUtils;
036import org.apache.shiro.subject.Subject;
037import org.slf4j.Logger;
038
039/**
040 * @author peichman
041 */
042public class ServletContainerAuthFilter implements Filter {
043
044    private static final Logger log = getLogger(ServletContainerAuthFilter.class);
045
046    /**
047     * User role for Fedora's admin users
048     */
049    public static final String FEDORA_ADMIN_ROLE = "fedoraAdmin";
050
051    /**
052     * User role for Fedora's ordinary users
053     */
054    public static final String FEDORA_USER_ROLE = "fedoraUser";
055
056    // TODO: configurable set of role names: https://jira.duraspace.org/browse/FCREPO-2770
057    private static final String[] ROLE_NAMES = { FEDORA_ADMIN_ROLE, FEDORA_USER_ROLE };
058
059    @Override
060    public void init(final FilterConfig filterConfig) {
061        // this method intentionally left empty
062    }
063
064    @Override
065    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
066            throws IOException, ServletException {
067        final HttpServletRequest httpRequest = (HttpServletRequest) request;
068        final Principal servletUser = httpRequest.getUserPrincipal();
069        final Subject currentUser = SecurityUtils.getSubject();
070
071        if (servletUser != null) {
072            log.debug("There is a servlet user: {}", servletUser.getName());
073            final Set<String> roles = new HashSet<>();
074            for (String roleName : ROLE_NAMES) {
075                log.debug("Testing role {}", roleName);
076                if (httpRequest.isUserInRole(roleName)) {
077                    log.debug("Servlet user {} has servlet role: {}", servletUser.getName(), roleName);
078                    roles.add(roleName);
079                }
080            }
081            final ContainerAuthToken token = new ContainerAuthToken(servletUser.getName(), roles);
082            log.debug("Credentials for servletUser = {}", token.getCredentials());
083            currentUser.login(token);
084        } else {
085            log.debug("Anonymous request");
086            // ensure the user is actually logged out
087            currentUser.logout();
088        }
089        chain.doFilter(request, response);
090    }
091
092    @Override
093    public void destroy() {
094        // this method intentionally left empty
095    }
096
097}