001/*
002 * Copyright 2015 DuraSpace, Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fcrepo.auth.common;
017
018import static java.util.Collections.emptySet;
019
020import org.modeshape.jcr.api.ServletCredentials;
021import org.slf4j.Logger;
022import org.slf4j.LoggerFactory;
023
024import javax.jcr.Credentials;
025import javax.servlet.http.HttpServletRequest;
026
027import java.security.Principal;
028import java.util.HashSet;
029import java.util.Set;
030
031/**
032 * An example principal provider that extracts principals from request headers.
033 *
034 * @author Gregory Jansen
035 * @author Mike Daines
036 * @see PrincipalProvider
037 */
038public class HttpHeaderPrincipalProvider implements PrincipalProvider {
039
040    protected static class HttpHeaderPrincipal implements Principal {
041
042        private final String name;
043
044        HttpHeaderPrincipal(final String name) {
045            this.name = name;
046        }
047
048        @Override
049        public String getName() {
050            return name;
051        }
052
053        @Override
054        public String toString() {
055            return name;
056        }
057
058        @Override
059        public boolean equals(final Object o) {
060            if (o instanceof HttpHeaderPrincipal) {
061                return ((HttpHeaderPrincipal) o).getName().equals(
062                        this.getName());
063            }
064            return false;
065        }
066
067        @Override
068        public int hashCode() {
069            if (name == null) {
070                return 0;
071            }
072            return name.hashCode();
073        }
074
075    }
076
077    private String headerName;
078
079    private String separator = "";
080
081    private static final Logger LOGGER = LoggerFactory.getLogger(HttpHeaderPrincipalProvider.class);
082
083    /**
084     * @param headerName The name of the header from which to extract principals
085     */
086    public void setHeaderName(final String headerName) {
087        this.headerName = headerName;
088    }
089
090    /**
091     * @param separator The string by which to split header values
092     */
093    public void setSeparator(final String separator) {
094        this.separator = separator;
095    }
096
097    /*
098     * (non-Javadoc)
099     * @see
100     * org.fcrepo.auth.PrincipalProvider#getPrincipals(javax.jcr.Credentials)
101     */
102    @Override
103    public Set<Principal> getPrincipals(final Credentials credentials) {
104        LOGGER.debug("Checking for principals using {}", HttpHeaderPrincipalProvider.class.getSimpleName());
105
106        if (headerName == null || separator == null) {
107            LOGGER.debug("headerName or separator not initialized");
108            return emptySet();
109        }
110
111        LOGGER.debug("Trying to get principals from header: {}; separator: {}", headerName, separator);
112
113        if (!(credentials instanceof ServletCredentials)) {
114            LOGGER.debug("Credentials is not an instanceof ServletCredentials");
115            return emptySet();
116        }
117
118        final ServletCredentials servletCredentials =
119                (ServletCredentials) credentials;
120
121        final HttpServletRequest request = servletCredentials.getRequest();
122
123        if (request == null) {
124            LOGGER.debug("Servlet request from servletCredentials was null");
125            return emptySet();
126        }
127
128        final String value = request.getHeader(headerName);
129
130        if (value == null) {
131            LOGGER.debug("Value for header {} is null", headerName);
132            return emptySet();
133        }
134
135        final String[] names = value.split(separator);
136
137        final Set<Principal> principals = new HashSet<>();
138
139        for (final String name : names) {
140            LOGGER.debug("Adding HTTP header-provided principal: {}", name.trim());
141            principals.add(new HttpHeaderPrincipal(name.trim()));
142        }
143
144        return principals;
145
146    }
147
148}