/* * JOSSO: Java Open Single Sign-On * * Copyright 2004-2009, Atricore, Inc. * * This 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 software 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. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.josso.agent.http; import org.josso.agent.*; import org.josso.auth.util.CipherUtil; import org.josso.gateway.SSONameValuePair; import org.josso.gateway.identity.SSORole; import org.josso.gateway.identity.SSOUser; import org.josso.gateway.identity.exceptions.SSOIdentityException; import org.josso.gateway.identity.service.SSOIdentityManagerService; import javax.security.auth.login.LoginException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpUtils; import javax.servlet.http.Cookie; import java.security.Principal; import java.util.*; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; /** * @author <a href="mailto:sgonzalez@atricore.org">Sebastian Gonzalez Oyuela</a> * @version $Rev: 608 $ $Date: 2008-08-21 12:35:13 -0300 (Thu, 21 Aug 2008) $ */ public abstract class HttpSSOAgent extends AbstractSSOAgent { private static final String DEFAULT_JOSSO_LOGIN_URI = "/josso_login/"; private static final String DEFAULT_JOSSO_USER_LOGIN_URI = "/josso_user_login/"; private static final String DEFAULT_JOSSO_SECURITY_CHECK_URI = "/josso_security_check"; private static final String DEFAULT_JOSSO_LOGOUT_URI = "/josso_logout/"; private static final String DEFAULT_JOSSO_AUTHENTICATION_URI = "/josso_authentication/"; private String _jossoLoginUri = DEFAULT_JOSSO_LOGIN_URI; private String _jossoUserLoginUri = DEFAULT_JOSSO_USER_LOGIN_URI; private String _jossoSecurityCheckUri = DEFAULT_JOSSO_SECURITY_CHECK_URI; private String _jossoLogoutUri = DEFAULT_JOSSO_LOGOUT_URI; private String _jossoAuthenticationUri = DEFAULT_JOSSO_AUTHENTICATION_URI; private String _uriEncoding; private List<FrontChannelParametersBuilder> _builders = new ArrayList<FrontChannelParametersBuilder>(); private List<AutomaticLoginStrategy> _automaticStrategies = new ArrayList<AutomaticLoginStrategy>(); public void start() { super.start(); // Automatically register default strategy if (_automaticStrategies.isEmpty()) { _automaticStrategies.add(new DefaultAutomaticLoginStrategy(org.josso.agent.Constants.JOSSO_AUTH_LOGIN_SUFFICIENT)); } for (AutomaticLoginStrategy as : _automaticStrategies) { if (as instanceof AbstractAutomaticLoginStrategy) { ((AbstractAutomaticLoginStrategy)as).setAgent(this); } } } /** * By default we do not require to authenticate all requests. */ protected boolean isAuthenticationAlwaysRequired() { return false; } protected void propagateSecurityContext(SSOAgentRequest request, Principal principal) { HttpSSOAgentRequest servletSSOAgentRequest = (HttpSSOAgentRequest) request; SSOPartnerAppConfig partnerAppConfig; String contextPath = servletSSOAgentRequest.getRequest().getContextPath(); // In catalina, the empty context is considered the root context if ("".equals(contextPath)) contextPath = "/"; partnerAppConfig = getPartnerAppConfig(servletSSOAgentRequest.getRequest().getServerName(), contextPath ); if (partnerAppConfig.getSecurityContextPropagationConfig() == null) { // No security propagation configuration found, ignore this. return; } SSOIdentityManagerService im = partnerAppConfig.getIdentityManagerService(); if (im == null) { im = getSSOIdentityManager(); } String binding = partnerAppConfig.getSecurityContextPropagationConfig().getBinding(); String userPlaceHolder = partnerAppConfig.getSecurityContextPropagationConfig().getUserPlaceHolder(); String rolesPlaceHolder = partnerAppConfig.getSecurityContextPropagationConfig().getRolesPlaceHolder(); String propertiesPlaceholder = partnerAppConfig.getSecurityContextPropagationConfig().getPropertiesPlaceHolder(); String user = principal.getName(); String nodeId = request.getNodeId(); if (binding != null && userPlaceHolder != null && rolesPlaceHolder != null && propertiesPlaceholder != null) { SSORole[] roleSets; try { if (nodeId != null && !"".equals(nodeId)) { NodeServices svcs = servicesByNode.get(nodeId); if (svcs != null) { roleSets = svcs.getIm().findRolesBySSOSessionId(request.getRequester(), servletSSOAgentRequest.getSessionId()); } else { roleSets = im.findRolesBySSOSessionId(request.getRequester(), servletSSOAgentRequest.getSessionId()); } } else { roleSets = im.findRolesBySSOSessionId(request.getRequester(), servletSSOAgentRequest.getSessionId()); } } catch (SSOIdentityException e) { if (debug > 0) log("Error fetching roles for SSO Session [" + servletSSOAgentRequest.getSessionId() + "]" + " on attempting to propagate security context, aborting"); return; } HttpServletRequest hreq = servletSSOAgentRequest.getRequest(); if (binding.equalsIgnoreCase("HTTP_HEADERS")) { HashMap headers = new HashMap(); List users = new ArrayList(); users.add(user); headers.put(userPlaceHolder, users); if (debug > 0) log("Propagated user [" + user + "] onto HTTP Header [" + userPlaceHolder + "]"); List roles = new ArrayList(); for (int i = 0; i < roleSets.length; i++) { SSORole roleSet = roleSets[i]; roles.add(roleSet.getName()); if (debug > 0) log("Propagated role [" + roleSet.getName() + "] onto HTTP_HEADERS based security context"); } headers.put(rolesPlaceHolder, roles); hreq.setAttribute(SecurityContextExporterFilter.SECURITY_CONTEXT_BINDING, SecurityContextExporterFilter.HTTP_HEADERS_BINDING); hreq.setAttribute(SecurityContextExporterFilter.SECURITY_CONTEXT_CONTENT, headers); } else if (binding.equalsIgnoreCase("HREQ_ATTRS")) { HashMap attrs = new HashMap(); attrs.put(userPlaceHolder, user); for (int i = 0; i < roleSets.length; i++) { SSORole roleSet = roleSets[i]; attrs.put(rolesPlaceHolder + "_" + i, roleSet.getName()); if (debug > 0) log("Propagated role [" + roleSet.getName() + "] onto HREQ_ATTRS based security context"); } SSOUser usr = (SSOUser) principal; if (usr.getProperties() != null) { //Properties props = new Properties(); for (int i = 0 ; i < usr.getProperties().length ; i++) { attrs.put(propertiesPlaceholder + "_" + usr.getProperties()[i].getName(), usr.getProperties()[i].getValue()); if (debug > 0) log("Propagated role [" + usr.getProperties()[i].getName() + "=" + usr.getProperties()[i].getValue() +"] onto HREQ_ATTRS based security context"); } } hreq.setAttribute(SecurityContextExporterFilter.SECURITY_CONTEXT_CONTENT, attrs); hreq.setAttribute(SecurityContextExporterFilter.SECURITY_CONTEXT_BINDING, SecurityContextExporterFilter.HTTP_REQ_ATTRS_BINDING); } } } /** * @deprecated * @param hreq * @return */ public boolean isAutomaticLoginRequired(HttpServletRequest hreq) { return isAutomaticLoginRequired(hreq, null); } /** * 1) Required - The LoginModule is required to succeed. * If it succeeds or fails, authentication still continues * to proceed down the LoginModule list. * * 3) Sufficient - The LoginModule is not required to * succeed. If it does succeed, control immediately * returns to the application (authentication does not * proceed down the LoginModule list). * If it fails, authentication continues down the * LoginModule list. * * 4) Optional - The LoginModule is not required to * succeed. If it succeeds or fails, * authentication still continues to proceed down the * LoginModule list. */ public boolean isAutomaticLoginRequired(HttpServletRequest hreq, HttpServletResponse hres) { // If any required module returns false, this will be false Boolean requiredFlag = null; // If any sufficient module returns true, this will be true Boolean sufficientFlag = null; for (AutomaticLoginStrategy as : _automaticStrategies) { if (as.getMode().equals(org.josso.agent.Constants.JOSSO_AUTH_LOGIN_SUFFICIENT)) { if (as.isAutomaticLoginRequired(hreq, hres)) { sufficientFlag = true; break; // Stop evaluation } } if (as.getMode().equals(org.josso.agent.Constants.JOSSO_AUTH_LOGIN_REQUIRED)) { if (!as.isAutomaticLoginRequired(hreq, hres)) { requiredFlag = false; } else if (requiredFlag == null) { requiredFlag = true; } } // This does not affect the outcome of the evaluation if (as.getMode().equals(org.josso.agent.Constants.JOSSO_AUTH_LOGIN_OPTIONAL)) { as.isAutomaticLoginRequired(hreq, hres); } } // If any required module returned a value, use it. if (requiredFlag != null) { return requiredFlag; } // If any sufficient modules returned a value, use it; otherwise return false. return sufficientFlag != null && sufficientFlag; } /** * @deprecated * @param hreq */ public void clearAutomaticLoginReferer(HttpServletRequest hreq) { clearAutomaticLoginReferer(hreq, null); } public void clearAutomaticLoginReferer(HttpServletRequest hreq, HttpServletResponse hres) { removeAttribute(hreq, hres, "JOSSO_AUTOMATIC_LOGIN_REFERER"); } /** * This method builds a logout URL based on a HttpServletRequest. The url contains all necessary parameters * required by the front-channel part of the SSO protocol. * * @deprecated * * @return */ public String buildLogoutUrl(HttpServletRequest hreq) { return buildLogoutUrl(hreq, "/"); } /** * This method builds a logout URL based on a HttpServletRequest. The url contains all necessary parameters * required by the front-channel part of the SSO protocol. * * @return */ public String buildLogoutUrl(HttpServletRequest hreq, SSOPartnerAppConfig cfg) { return buildLogoutUrl(hreq, cfg.getDefaultResource() != null ? cfg.getDefaultResource() : "/"); } /** * This method builds a logout URL based on a HttpServletRequest. The url contains all necessary parameters * required by the front-channel part of the SSO protocol. * * @return */ public String buildLogoutUrl(HttpServletRequest hreq, String backToPath) { // Support specifying an external form for each application. SSOPartnerAppConfig appCfg = getPartnerAppConfig(hreq.getServerName(), hreq.getContextPath()); String logoutUrl = null; if (appCfg != null && appCfg.getGatewayLogoutUrl() != null) { logoutUrl = appCfg.getGatewayLogoutUrl(); } else { logoutUrl = getGatewayLogoutUrl(); } String backto = buildBackToURL(hreq, backToPath); logoutUrl = logoutUrl + (logoutUrl.indexOf('?') >= 0 ? "&" : "?") + "josso_back_to=" + (backto != null ? backto : "NA"); logoutUrl += buildLogoutUrlParams(hreq); return logoutUrl; } /** * This method builds a login URL based on a HttpServletRequest. The url contains all necessary parameters * required by the front-channel part of the SSO protocol. */ public String buildLoginUrl(HttpServletRequest hreq) { // Support specifying an external form for each application. SSOPartnerAppConfig appCfg = getPartnerAppConfig(hreq.getServerName(), hreq.getContextPath()); String loginUrl = null; if (appCfg != null && appCfg.getGatewayLoginUrl() != null) { loginUrl = appCfg.getGatewayLoginUrl(); } else { loginUrl = getGatewayLoginUrl(); } if (hreq.getParameter("josso_force_authn") != null && Boolean.parseBoolean(hreq.getParameter("josso_force_authn"))) { loginUrl = loginUrl + (loginUrl.indexOf('?') >= 0 ? "&" : "?") + "josso_cmd=login_force"; } if (hreq.getParameter("josso_authn_ctx") != null) { loginUrl = loginUrl + (loginUrl.indexOf('?') >= 0 ? "&" : "?") + "josso_authn_ctx=" + hreq.getParameter("josso_authn_ctx"); } String backto = buildBackToURL(hreq, getJossoSecurityCheckUri()); loginUrl = loginUrl + (loginUrl.indexOf('?') >= 0 ? "&" : "?") + "josso_back_to=" + (backto != null ? backto : "NA"); // Add login URL parameters loginUrl += buildLoginUrlParams(hreq); return loginUrl; } /** * This method builds a login URL based on a HttpServletRequest. The url contains all necessary parameters * required by the front-channel part of the SSO protocol. */ public String buildLoginOptionalUrl(HttpServletRequest hreq) { // Support specifying an external form for each application. SSOPartnerAppConfig appCfg = getPartnerAppConfig(hreq.getServerName(), hreq.getContextPath()); String loginUrl = null; if (appCfg != null && appCfg.getGatewayLoginUrl() != null) { loginUrl = appCfg.getGatewayLoginUrl(); } else { loginUrl = getGatewayLoginUrl(); } // Add back_to param if available String backto = buildBackToURL(hreq, getJossoSecurityCheckUri()); loginUrl = loginUrl + (loginUrl.indexOf('?') >= 0 ? "&" : "?") + "josso_cmd=login_optional"; if (backto != null) loginUrl += "&josso_back_to=" + backto; else loginUrl += "&josso_back_to=NA"; // Add login URL parameters loginUrl += buildLoginUrlParams(hreq); return loginUrl; } /** * This method builds the back_to URL value pointing to the given URI. * <p/> * The determines the host used to build the back_to URL in the following order : * <p/> * First, checks the singlePointOfAccess agent's configuration property. * Then checks the reverse-proxy-host HTTP header value from the request. * Finally uses current host name. */ public String buildBackToURL(HttpServletRequest hreq, String uri) { String backto = null; // Check if back_to needs to be added to the URL (JOSSO 2 does not require back_to) SSOPartnerAppConfig partnerAppConfig = getPartnerAppConfig(hreq.getServerName(), hreq.getContextPath()); if (partnerAppConfig != null && partnerAppConfig.isDisableBackTo()) { return null; } // Build the back to url. String contextPath = hreq.getContextPath(); // This is the root context if (contextPath == null || "".equals(contextPath)) contextPath = "/"; String reverseProxyHost = hreq.getHeader(org.josso.gateway.Constants.JOSSO_REVERSE_PROXY_HEADER); String singlePointOfAccess = getSinglePointOfAccess(); if (singlePointOfAccess != null) { // Using single-point of access configuration. if (debug >= 1) log("josso_back_to option : singlePointOfAccess: " + singlePointOfAccess); backto = singlePointOfAccess + contextPath + uri; } else if (reverseProxyHost != null) { // Using reverse proxy host header. if (debug >= 1) log("josso_back_to option : reverse-proxy-host: " + reverseProxyHost); backto = reverseProxyHost + contextPath + uri; } else { // Using default host StringBuffer mySelf = HttpUtils.getRequestURL(hreq); try { java.net.URL url = new java.net.URL(mySelf.toString()); backto = url.getProtocol() + "://" + url.getHost() + ((url.getPort() > 0) ? ":" + url.getPort() : ""); } catch (java.net.MalformedURLException e) { throw new RuntimeException(e); } backto += (contextPath.endsWith("/") ? contextPath.substring(0, contextPath.length() - 1) : contextPath) + uri; } if (debug >= 1) log("Using josso_back_to : " + backto); return backto; } public String buildPostAuthUrl(HttpServletResponse hres, String requestURI, String postAuthURI) { // TODO : Is there a better way to do this ? String encURL = requestURI.replaceAll("&", "%26").replaceAll("\\?", "%3F"); return hres.encodeRedirectURL(postAuthURI + "?josso_original_resource=" + hres.encodeURL(encURL)); } /** * This creates a new JOSSO Cookie for the given path and value. * * @param path the path associated with the cookie, normaly the partner application context. * @param value the SSO Session ID * @return */ public Cookie newJossoCookie(String path, String value, boolean secure) { // Some browsers don't like cookies without paths. This is useful for partner applications configured in the root context if (path == null || "".equals(path)) path = "/"; Cookie ssoCookie = new Cookie(org.josso.gateway.Constants.JOSSO_SINGLE_SIGN_ON_COOKIE, value); ssoCookie.setMaxAge(-1); ssoCookie.setPath(path); ssoCookie.setSecure(secure); // TODO : Check domain ? //ssoCookie.setDomain(cfg.getSessionTokenScope()); return ssoCookie; } @SuppressWarnings("unchecked") public String buildAutomaticSubmitForm(HttpServletRequest request){ //TODO - remove permanently return null; } /** * This method builds request URL parameters that will be sent to the gateway when attempting logins and identity assertions * trhough the front channel (HTTP) * * @param hreq * @return */ protected String buildLoginUrlParams(HttpServletRequest hreq) { SSOPartnerAppConfig cfg = super.getPartnerAppConfig(hreq.getServerName(), hreq.getContextPath()); String urlParams = ""; for (FrontChannelParametersBuilder builder : _builders) { SSONameValuePair[] params = builder.buildParamters(cfg, hreq); for (SSONameValuePair param : params) { urlParams += "&" + param.getName() + "=" + param.getValue(); } } return urlParams; } /** * This method builds request URL parameters that will be sent to the gateway when attempting logins and identity assertions * trhough the front channel (HTTP) * * @param hreq * @return */ protected String buildLogoutUrlParams(HttpServletRequest hreq) { SSOPartnerAppConfig cfg = super.getPartnerAppConfig(hreq.getServerName(), hreq.getContextPath()); String urlParams = ""; for (FrontChannelParametersBuilder builder : _builders) { SSONameValuePair[] params = builder.buildParamters(cfg, hreq); for (SSONameValuePair param : params) { urlParams += "&" + param.getName() + "=" + param.getValue(); } } return urlParams; } @SuppressWarnings("unchecked") @Override protected void sendCustomAuthentication(SSOAgentRequest request) throws IOException { HttpServletRequest hreq = ((HttpSSOAgentRequest) request).getRequest(); HttpServletResponse hres = ((HttpSSOAgentRequest) request).getResponse(); prepareNonCacheResponse(hres); SSOPartnerAppConfig cfg = this.getPartnerAppConfig(hreq.getServerName(), hreq.getContextPath()); String splash_resource = null; /* If this is an authentication request, our splash resource will be one of the following (in the given order): * 1. submitted josso_splash_resource parameter * 2. default splash resource, defined in josso-agent-config * TODO : Referer values should be handled by agent when processing LOGIN_REQUESTS (josso_login) 3. value from referrer header * * If this is not authentication request, splash resource will be request URI */ if (hreq.getRequestURI().endsWith(this.getJossoAuthenticationUri())) { //try josso_splash_resource defined as hidden field splash_resource = hreq.getParameter(Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); if( splash_resource == null || "".equals(splash_resource)){ if(cfg != null){ splash_resource = cfg.getSplashResource(); } /* TODO :Verify this! Agents should store referer values as SAVED_REQUESTS when processing a login or automatic request if(splash_resource == null || "".equals(splash_resource)){ //fall back to referer splash_resource = hreq.getHeader("referer"); } */ } } else { if (debug > 0) log("sendCustomAuthentication executed but URL does not match AUTHENTICATION URI"); // TODO : Verify this! We should never get here .. StringBuffer sb = new StringBuffer(hreq.getRequestURI()); if (hreq.getQueryString() != null) { sb.append('?'); sb.append(hreq.getQueryString()); } String[] uriArray = new String[1]; splash_resource = sb.toString(); } if (debug > 0) log("Storing Splash resource '"+splash_resource+"'"); setAttribute(hreq, hres, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER, splash_resource); StringBuilder sb = new StringBuilder(); // TODO : Use a template instead ? sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\n" + "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n" + "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n" + "<body onload=\"document.forms[0].submit()\">\n" + "<noscript>\n" + "<p>\n" + "<strong>Note:</strong> Since your browser does not support JavaScript,\n" + "you must press the Continue button once to proceed.\n" + "</p>\n" + "</noscript>\n" + "<form action=\"").append(getGatewayLoginUrl()). append("\" method=\"post\" name=\"usernamePasswordLoginForm\" enctype=\"application/x-www-form-urlencoded\">\n" + " <div>"); //copy all submitted parameters into hidden fields Enumeration paramNames = hreq.getParameterNames(); while (paramNames.hasMoreElements()) { String paramName = (String) paramNames.nextElement(); String paramValue = hreq.getParameter(paramName); if (!Constants.JOSSO_SPLASH_RESOURCE_PARAMETER.equals(paramName)) { sb.append("\n <input type=\"hidden\" value=\"").append(paramValue).append("\" name=\"").append(paramName).append("\" />"); } } // sb.append("\n <input type=\"hidden\" name=\"josso_back_to\"value=\"").append(buildBackToURL(hreq, getJossoSecurityCheckUri())).append("\"/>\n"). sb.append("\n <noscript><input type=\"submit\" value=\"Continue\"/></noscript>\n" + " </div>\n" + "</form>\n" + "</body>\n" + "</html>"); hres.setContentType("text/html"); PrintWriter out = hres.getWriter(); out.print(sb.toString()); if (debug >= 1) { log("Sending an automatic post form : \n" + sb.toString()); } out.flush(); } /** * Sets non cache headers in HttpServletResponse * @param response */ public void prepareNonCacheResponse(HttpServletResponse response) { response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); response.setHeader("Expires", "0"); } /** * Checks if the requested resource is subject to SSO protection * (it compares the request path against configured <ignore-url-patterns>). * * @param cfg partner application configuration * @param request http request * @return true if requested resource should be ignored, false otherwise */ public boolean isResourceIgnored(SSOPartnerAppConfig cfg, HttpServletRequest request) { // There are some url-patterns to ignore String[] ignoredUrlPatterns = cfg.getIgnoredUrlPatterns(); if (debug >= 1) log("Found [" + (ignoredUrlPatterns!= null ? ignoredUrlPatterns.length+"" : "no") + "] ignored url patterns "); if (ignoredUrlPatterns != null && ignoredUrlPatterns.length > 0) { String requestPath = request.getServletPath(); // Add the path info, if there is any String pathInfo = request.getPathInfo(); if (pathInfo != null) { requestPath += pathInfo; } for (int i=0; i<ignoredUrlPatterns.length; i++) { String ignoredUrlPattern = ignoredUrlPatterns[i]; if (matchPattern(requestPath, ignoredUrlPattern)) { // We should ignore this URI, it's not subject to SSO protection if (debug >= 1) log("Not subject to SSO protection : url-pattern:" + ignoredUrlPattern); return true; } } } return false; } /** * Does the specified request path match the specified URL pattern? * This method follows the same rules (in the same order) as those used * for mapping requests to servlets. * * @param path Context-relative request path to be checked * (must start with '/') * @param pattern URL pattern to be compared against */ protected boolean matchPattern(String path, String pattern) { // Normalize the argument strings if ((path == null) || (path.length() == 0)) path = "/"; if ((pattern == null) || (pattern.length() == 0)) pattern = "/"; // Check for exact match if (path.equals(pattern)) return (true); // Check for path prefix matching if (pattern.startsWith("/") && pattern.endsWith("/*")) { pattern = pattern.substring(0, pattern.length() - 2); if (pattern.length() == 0) return (true); // "/*" is the same as "/" if (path.endsWith("/")) path = path.substring(0, path.length() - 1); while (true) { if (pattern.equals(path)) return (true); int slash = path.lastIndexOf('/'); if (slash <= 0) break; path = path.substring(0, slash); } return (false); } // Check for suffix matching if (pattern.startsWith("*.")) { int slash = path.lastIndexOf('/'); int period = path.lastIndexOf('.'); if ((slash >= 0) && (period > slash) && path.endsWith(pattern.substring(1))) { return (true); } return (false); } // Check for universal mapping if (pattern.equals("/")) return (true); return (false); } /** * Retreives the list of roles for the given SSO id. * * @param ssoSessionId SSO id * @return array of user roles * @throws LoginException */ public SSORole[] getRoleSets(String requester, String ssoSessionId, String nodeId) { try { SSOAgentRequest request = _currentRequest.get(); SSOIdentityManagerService im = null; if (request != null) { im = request.getConfig(this).getIdentityManagerService(); } if (im == null) { im = this.getSSOIdentityManager(); if (nodeId != null && !"".equals(nodeId)) { NodeServices svcs = servicesByNode.get(nodeId); if (svcs != null && svcs.getIm() != null) { im = svcs.getIm(); } } } SSORole[] roleSets = im.findRolesBySSOSessionId(requester, ssoSessionId); return roleSets; } catch(Exception e) { log("Error finding roles for : " + ssoSessionId, e); throw new RuntimeException("Error finding roles for : " + ssoSessionId); } } public String getJossoLoginUri() { return _jossoLoginUri; } public void setJossoLoginUri(String jossoLoginUri) { _jossoLoginUri = jossoLoginUri; } public String getJossoUserLoginUri() { return _jossoUserLoginUri; } public void setJossoUserLoginUri(String jossoUserLoginUri) { _jossoUserLoginUri = jossoUserLoginUri; } public String getJossoSecurityCheckUri() { return _jossoSecurityCheckUri; } public void setJossoSecurityCheckUri(String jossoSecurityCheckUri) { _jossoSecurityCheckUri = jossoSecurityCheckUri; } public String getJossoLogoutUri() { return _jossoLogoutUri; } public void setJossoLogoutUri(String jossoLogoutUri) { _jossoLogoutUri = jossoLogoutUri; } public String getJossoAuthenticationUri(){ return _jossoAuthenticationUri; } public void setJossoAuthenticationUri(String jossoAuthenticationUri) { _jossoAuthenticationUri = jossoAuthenticationUri; } // --------------------------- Spring friendly public void setParametersBuilders(List<FrontChannelParametersBuilder> builders) { this._builders = builders; } public List<FrontChannelParametersBuilder> getParametersBuilders() { return _builders; } /** * Sets attribute as a cookie (if stateOnClient enabled) * or in the http session. * Value is base64 encoded. * * @param hreq http request * @param hres http response * @param name attribute name * @param value attribute value */ public void setAttribute(HttpServletRequest hreq, HttpServletResponse hres, String name, String value) { if (isStateOnClient()) { Set<String> removed = (Set<String>) hreq.getAttribute("org.josso.attrs.removed"); if (removed == null) removed = new HashSet<String>(); if (removed.contains(name)) removed.remove(name); log("Storing attribute " + name + "=" + value + " client side"); if (hres == null) throw new IllegalArgumentException("HTTP Servlet response cannot be null. Are you using any deprecated operations?"); String cookieValue = null; try { // TODO: upgrade to commons-codec 1.4 and use URL-safe mode? cookieValue = CipherUtil.encodeBase64(value.getBytes("UTF-8")); cookieValue = URLEncoder.encode(cookieValue, "UTF-8"); } catch (UnsupportedEncodingException e) { log("Base64 encoding failed : " + value, e); cookieValue = value; } // Store value as session cookie Cookie cookie = new Cookie(name, cookieValue); cookie.setPath(hreq.getContextPath().equals("") ? "/" : hreq.getContextPath()); cookie.setMaxAge(-1); cookie.setSecure(hreq.isSecure()); hres.addCookie(cookie); // Local copy hreq.setAttribute(name, value); } else { log("Storing attribute " + name + "=" + value + " server side"); // Use HTTP Session ( TODO : Use LocalSession instead ? ) hreq.getSession().setAttribute(name, value); } } /** * Retrieves attribute value from the cookie (if stateOnClient enabled) * or from the http session. * * @param hreq http request * @param name attribute name * @return attribute value */ public String getAttribute(HttpServletRequest hreq, String name) { if (isStateOnClient()) { Set<String> removed = (Set<String>) hreq.getAttribute("org.josso.attrs.removed"); if (removed == null) removed = new HashSet<String>(); if (removed.contains(name)) return null; // If a local value is present, use it. String vlocal = (String) hreq.getAttribute(name); if (vlocal != null && !"".equals(vlocal)) return vlocal; // Use a cookie value, if present Cookie[] cookies = hreq.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if (cookie.getName().equals(name)) { String cookieValue = cookie.getValue(); String value = null; try { // TODO: upgrade to commons-codec 1.4 and use URL-safe mode? cookieValue = URLDecoder.decode(cookieValue, "UTF-8"); value = new String(CipherUtil.decodeBase64(cookieValue)); } catch (UnsupportedEncodingException e) { log("Base64 decoding failed : " + cookieValue, e); value = cookieValue; } if (value == null || value.equals("-") || value.equals("")) return null; return value; } } } return null; } else { // Use HTTP Session ( TODO : Use LocalSession instead ? ) return (String) hreq.getSession().getAttribute(name); } } /** * Removes attribute with the given name * (removes the cookie if stateOnClient enabled, * otherwise it removes it from the http session). * * @param hreq http request * @param hres http response * @param name attribute name */ public void removeAttribute(HttpServletRequest hreq, HttpServletResponse hres, String name) { if (isStateOnClient()) { Set<String> removed = (Set<String>) hreq.getAttribute("org.josso.attrs.removed"); if (removed == null) removed = new HashSet<String>(); log("Remove attribute " + name + " from client side"); // Use a cookie // Store value as session cookie Cookie cookie = new Cookie(name, (String) "-"); cookie.setPath(hreq.getContextPath()); cookie.setMaxAge(0); cookie.setSecure(hreq.isSecure()); hres.addCookie(cookie); // Mark this as removed removed.add(name); // Local copy hreq.removeAttribute(name); } else { log("Remove attribute " + name + " from server side"); // Use HTTP Session ( TODO : Use LocalSession instead ? ) hreq.getSession().removeAttribute(name); } } public List<AutomaticLoginStrategy> getAutomaticLoginStrategies() { return _automaticStrategies; } public void setAutomaticLoginStrategies(List<AutomaticLoginStrategy> _automaticStrategies) { this._automaticStrategies = _automaticStrategies; } public void setUriEncoding(String uriEncoding) { this._uriEncoding = uriEncoding; } public String getUriEncoding() { return _uriEncoding; } public boolean isAgentReservedUri(String contextPath, String uri) { if (uri == null) return false; if (contextPath == null) contextPath = ""; // TODO : Cache URIs so we dont do this all the time. return uri.startsWith(contextPath + getJossoLoginUri()) || uri.startsWith(contextPath + getJossoSecurityCheckUri()) || uri.startsWith(contextPath + getJossoLogoutUri()) || uri.startsWith(contextPath + getJossoUserLoginUri()); } }