/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.security.sso.opensso.internal.servlet.filter;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.module.configuration.ConfigurationProvider;
import com.liferay.portal.kernel.security.sso.OpenSSO;
import com.liferay.portal.kernel.servlet.BaseFilter;
import com.liferay.portal.kernel.settings.CompanyServiceSettingsLocator;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.Portal;
import com.liferay.portal.kernel.util.URLCodec;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.security.sso.opensso.configuration.OpenSSOConfiguration;
import com.liferay.portal.security.sso.opensso.constants.OpenSSOConstants;
import com.liferay.portal.util.PropsValues;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* Participates in every login and logout that triggers an HTTP request to
* Liferay Portal.
*
* <p>
* For logout requests, this class invalidates the current session and redirects
* the browser to the configured OpenSSO server Logout URL. For login requests,
* it checks the token cookie to determine if the user is already authenticated
* with the OpenSSO server.
* </p>
*
* <p>
* If the token cookie validates, a new Liferay Portal session is started with
* the same token. Otherwise, an OpenSSO server login URL is constructed subject
* to whether or not the <code>AUTH_FORWARD_BY_LAST_PATH</code> system property
* is set.
* </p>
*
* <p>
* If it is, this class looks for a redirect parameter on the current request
* (falling back to the portal home URL). If the redirect parameter is not
* found, the filter uses the configured OpenSSO Login URL unmodified.
* </p>
*
* @author Brian Wing Shun Chan
* @author Raymond Augé
* @author Prashant Dighe
* @author Hugo Huijser
*/
@Component(
configurationPid = "com.liferay.portal.security.sso.opensso.configuration.OpenSSOConfiguration",
immediate = true,
property = {
"before-filter=Auto Login Filter", "dispatcher=FORWARD",
"dispatcher=REQUEST", "servlet-context-name=",
"servlet-filter-name=SSO Open SSO Filter",
"url-pattern=/c/portal/login", "url-pattern=/c/portal/logout"
},
service = Filter.class
)
public class OpenSSOFilter extends BaseFilter {
@Override
public boolean isFilterEnabled(
HttpServletRequest request, HttpServletResponse response) {
try {
long companyId = _portal.getCompanyId(request);
OpenSSOConfiguration openSSOConfiguration = getOpenSSOConfiguration(
companyId);
if (openSSOConfiguration.enabled() &&
Validator.isNotNull(openSSOConfiguration.loginURL()) &&
Validator.isNotNull(openSSOConfiguration.logoutURL()) &&
Validator.isNotNull(openSSOConfiguration.serviceURL())) {
return true;
}
}
catch (Exception e) {
_log.error(e, e);
}
return false;
}
@Override
protected Log getLog() {
return _log;
}
protected OpenSSOConfiguration getOpenSSOConfiguration(long companyId)
throws Exception {
return _configurationProvider.getConfiguration(
OpenSSOConfiguration.class,
new CompanyServiceSettingsLocator(
companyId, OpenSSOConstants.SERVICE_NAME));
}
@Override
protected void processFilter(
HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain)
throws Exception {
long companyId = _portal.getCompanyId(request);
OpenSSOConfiguration openSSOConfiguration = getOpenSSOConfiguration(
companyId);
String requestURI = GetterUtil.getString(request.getRequestURI());
if (requestURI.endsWith("/portal/logout")) {
HttpSession session = request.getSession();
session.invalidate();
response.sendRedirect(openSSOConfiguration.logoutURL());
return;
}
boolean authenticated = false;
try {
// LEP-5943
authenticated = _openSSO.isAuthenticated(
request, openSSOConfiguration.serviceURL());
}
catch (Exception e) {
_log.error(e, e);
processFilter(
OpenSSOFilter.class.getName(), request, response, filterChain);
return;
}
HttpSession session = request.getSession();
if (authenticated) {
// LEP-5943
String newSubjectId = _openSSO.getSubjectId(
request, openSSOConfiguration.serviceURL());
String oldSubjectId = (String)session.getAttribute(_SUBJECT_ID_KEY);
if (oldSubjectId == null) {
session.setAttribute(_SUBJECT_ID_KEY, newSubjectId);
}
else if (!newSubjectId.equals(oldSubjectId)) {
session.invalidate();
session = request.getSession();
session.setAttribute(_SUBJECT_ID_KEY, newSubjectId);
}
processFilter(
OpenSSOFilter.class.getName(), request, response, filterChain);
return;
}
else if (_portal.getUserId(request) > 0) {
session.invalidate();
}
if (!PropsValues.AUTH_FORWARD_BY_LAST_PATH ||
!openSSOConfiguration.loginURL().contains("/portal/login")) {
response.sendRedirect(openSSOConfiguration.loginURL());
return;
}
String currentURL = _portal.getCurrentURL(request);
String redirect = currentURL;
if (currentURL.contains("/portal/login")) {
redirect = ParamUtil.getString(request, "redirect");
if (Validator.isNull(redirect)) {
redirect = _portal.getPathMain();
}
}
redirect =
openSSOConfiguration.loginURL() +
URLCodec.encodeURL("?redirect=" + URLCodec.encodeURL(redirect));
response.sendRedirect(redirect);
}
@Reference(unbind = "-")
protected void setConfigurationProvider(
ConfigurationProvider configurationProvider) {
_configurationProvider = configurationProvider;
}
@Reference(unbind = "-")
protected void setOpenSSO(OpenSSO openSSO) {
_openSSO = openSSO;
}
private static final String _SUBJECT_ID_KEY = "open.sso.subject.id";
private static final Log _log = LogFactoryUtil.getLog(OpenSSOFilter.class);
private ConfigurationProvider _configurationProvider;
private OpenSSO _openSSO;
@Reference
private Portal _portal;
}