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