001/*
002 * (C) Copyright 2010-2018 Nuxeo (http://nuxeo.com/) and others.
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 *
016 * Contributors:
017 *     Nuxeo - initial API and implementation
018 */
019
020package org.nuxeo.ecm.platform.shibboleth.service;
021
022import static org.apache.commons.lang3.StringUtils.isNotEmpty;
023import static org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants.REDIRECT_URL;
024
025import java.io.UnsupportedEncodingException;
026import java.util.HashMap;
027import java.util.Map;
028
029import javax.servlet.http.HttpServletRequest;
030
031import org.nuxeo.common.utils.URIUtils;
032import org.nuxeo.ecm.platform.web.common.vh.VirtualHostHelper;
033import org.nuxeo.runtime.model.ComponentInstance;
034import org.nuxeo.runtime.model.DefaultComponent;
035
036import com.google.common.collect.BiMap;
037import com.google.common.collect.HashBiMap;
038
039public class ShibbolethAuthenticationServiceImpl extends DefaultComponent implements ShibbolethAuthenticationService {
040
041    public static final String CONFIG_EP = "config";
042
043    protected ShibbolethAuthenticationConfig config;
044
045    @Override
046    public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
047        if (CONFIG_EP.equals(extensionPoint)) {
048            config = (ShibbolethAuthenticationConfig) contribution;
049        }
050    }
051
052    public ShibbolethAuthenticationConfig getConfig() {
053        return config;
054    }
055
056    @Override
057    public String getLoginURL(String redirectURL) {
058        if (config == null || config.getLoginURL() == null) {
059            return null;
060        }
061
062        Map<String, String> urlParameters = new HashMap<>(1);
063        urlParameters.put(config.getLoginRedirectURLParameter(), redirectURL);
064        return URIUtils.addParametersToURIQuery(config.getLoginURL(), urlParameters);
065    }
066
067    @Override
068    public String getLogoutURL(String redirectURL) {
069        if (config == null || config.getLogoutURL() == null) {
070            return null;
071        }
072
073        Map<String, String> urlParameters = new HashMap<>(1);
074        urlParameters.put(config.getLogoutRedirectURLParameter(), redirectURL);
075        return URIUtils.addParametersToURIQuery(config.getLogoutURL(), urlParameters);
076    }
077
078    @Override
079    public String getLoginURL(HttpServletRequest request) {
080        String redirectUrl = VirtualHostHelper.getRedirectUrl(request);
081        request.getSession().setAttribute(REDIRECT_URL, redirectUrl);
082        return getLoginURL(redirectUrl);
083    }
084
085    @Override
086    public String getLogoutURL(HttpServletRequest request) {
087        return getLogoutURL((String) request.getSession().getAttribute(REDIRECT_URL));
088    }
089
090    @Override
091    public String getUserID(HttpServletRequest httpRequest) {
092        String idpUrl = httpRequest.getHeader(config.getIdpHeader());
093        String uidHeader = config.getUidHeaders().get(idpUrl);
094        if (uidHeader == null || readHeader(httpRequest, uidHeader) == null
095                || readHeader(httpRequest, uidHeader).isEmpty()) {
096            uidHeader = config.getDefaultUidHeader();
097        }
098        return readHeader(httpRequest, uidHeader);
099    }
100
101    @Override
102    public Map<String, Object> getUserMetadata(String userIdField, HttpServletRequest httpRequest) {
103        Map<String, Object> fieldMap = new HashMap<>(config.fieldMapping.size());
104        for (String key : config.getFieldMapping().keySet()) {
105            fieldMap.put(config.getFieldMapping().get(key), readHeader(httpRequest, key));
106        }
107        // Force userIdField to shibb userId value in case of the IdP do
108        // not use the same mapping as the default's one.
109        fieldMap.put(userIdField, getUserID(httpRequest));
110        return fieldMap;
111    }
112
113    @Override
114    public BiMap<String, String> getUserMetadata() {
115        BiMap<String, String> biMap = HashBiMap.create();
116        biMap.putAll(config.getFieldMapping());
117        return biMap;
118    }
119
120    protected String readHeader(HttpServletRequest request, String key) {
121        String value = request.getHeader(key);
122        if (isNotEmpty(value) && isNotEmpty(config.getHeaderEncoding())) {
123            try {
124                value = new String(value.getBytes("ISO-8859-1"), config.getHeaderEncoding());
125            } catch (UnsupportedEncodingException ignored) {
126                // Nothing
127            }
128        }
129        return value;
130    }
131}