<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
- <!-- Hook IdP sessions into HTTP servlet container sessions. -->
- <listener>
- <listener-class>edu.internet2.middleware.shibboleth.idp.session.ContainerSessionListener</listener-class>
- </listener>
+ <!-- Add IdP Session object to incoming profile requests -->
+ <filter>
+ <filter-name>IdPSessionFilter</filter-name>
+ <filter-class>edu.internet2.middleware.shibboleth.idp.session.IdPSessionFilter</filter-class>
+ </filter>
- <!--
- Session time inactivity timeout, in minutes.
-
- A timeout of 0 or less means the session never timesout. Such a setting is strongly discouraged and will
- almost certainly lead to memory exhaustion under moderate to heavy loads or in servers with prolonged uptime.
- -->
- <session-config>
- <session-timeout>30</session-timeout>
- </session-config>
+ <filter-mapping>
+ <filter-name>IdSessionFilter</filter-name>
+ <url-pattern>/profile/*</url-pattern>
+ </filter-mapping>
<!-- Profile Request Dispatcher -->
<servlet>
package edu.internet2.middleware.shibboleth.idp.authn;
import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
import java.util.List;
import javax.security.auth.Subject;
}
if (!loginContext.getAuthenticationAttempted()) {
- String shibSessionId = (String) httpSession.getAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE);
- Session shibSession = getSessionManager().getSession(shibSessionId);
+ Session shibSession = (Session) httpSession.getAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE);
AuthenticationMethodInformation authenticationMethod = getUsableExistingAuthenticationMethod(loginContext,
shibSession);
AuthenticationMethodInformation authenticationMethod) {
HttpSession httpSession = httpRequest.getSession();
- String shibSessionId = (String) httpSession.getAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE);
- Session shibSession = getSessionManager().getSession(shibSessionId);
+ Session shibSession = (Session) httpSession.getAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE);
LOG.debug("Populating login context with existing session and authentication method information.");
LoginContext loginContext = (LoginContext) httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
loginContext.setPrincipalName(principalName);
loginContext.setAuthenticationInstant(new DateTime());
- String shibSessionId = (String) httpSession.getAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE);
- Session shibSession = getSessionManager().getSession(shibSessionId);
-
+ Session shibSession = (Session) httpSession.getAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE);
if (shibSession == null) {
LOG.debug("Creating shibboleth session for principal {}", principalName);
-
- InetAddress addr;
- try {
- addr = InetAddress.getByName(httpRequest.getRemoteAddr());
- } catch (UnknownHostException ex) {
- addr = null;
- }
-
- shibSession = (Session) getSessionManager().createSession(addr, loginContext.getPrincipalName());
+ shibSession = (Session) getSessionManager().createSession(loginContext.getPrincipalName());
loginContext.setSessionID(shibSession.getSessionID());
- httpSession.setAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE, shibSession.getSessionID());
+ httpSession.setAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE, shibSession);
}
LOG.debug("Recording authentication and service information in Shibboleth session for principal: {}",
* @return user's session
*/
protected Session getUserSession(InTransport inTransport) {
- String sessionId = getUserSessionId(inTransport);
- return getSessionManager().getSession(sessionId);
- }
-
- /**
- * Gets the user's session ID from the current request.
- *
- * @param inTransport current inbound transport
- *
- * @return user's session ID
- */
- protected String getUserSessionId(InTransport inTransport) {
HttpServletRequest rawRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
-
- if (rawRequest != null) {
- return (String) rawRequest.getSession().getAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE);
- }
-
- return null;
+ return (Session) rawRequest.getAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE);
}
/**
import edu.internet2.middleware.shibboleth.common.util.HttpHelper;
import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
import edu.internet2.middleware.shibboleth.idp.authn.Saml2LoginContext;
+import edu.internet2.middleware.shibboleth.idp.session.Session;
/** SAML 2.0 SSO request profile handler. */
public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
statement.setAuthnContext(authnContext);
statement.setAuthnInstant(loginContext.getAuthenticationInstant());
- // TODO
- statement.setSessionIndex(null);
+ Session session = getUserSession(requestContext.getInboundMessageTransport());
+ if(session != null){
+ statement.setSessionIndex(session.getSessionID());
+ }
if (loginContext.getAuthenticationDuration() > 0) {
statement.setSessionNotOnOrAfter(loginContext.getAuthenticationInstant().plus(
--- /dev/null
+/*
+ * Copyright 2008 University Corporation for Advanced Internet Development, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.internet2.middleware.shibboleth.idp.session;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.joda.time.DateTime;
+
+import edu.internet2.middleware.shibboleth.common.session.SessionManager;
+
+/**
+ * A filter that adds the current users {@link Session} the request, if the user has a session.
+ */
+public class IdPSessionFilter implements Filter {
+
+ /** Name of the IdP Cookie containing the IdP session ID. */
+ public static final String IDP_SESSION_COOKIE_NAME = "_idp_session";
+
+ /** IdP session manager. */
+ private SessionManager<Session> sessionManager;
+
+ /** {@inheritDoc} */
+ public void destroy() {
+
+ }
+
+ /** {@inheritDoc} */
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException,
+ ServletException {
+ HttpServletRequest httpRequest = (HttpServletRequest) request;
+ HttpServletResponse httpResponse = (HttpServletResponse) response;
+
+ Cookie idpSessionCookie = getIdPSessionCookie(httpRequest);
+ if (idpSessionCookie != null) {
+ Session idpSession = sessionManager.getSession(idpSessionCookie.getValue());
+ if (idpSession != null) {
+ idpSession.setLastActivityInstant(new DateTime());
+ httpRequest.setAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE, idpSession);
+ addIdPSessionCookieToResponse(httpRequest, httpResponse, idpSession);
+ }
+ }
+
+ filterChain.doFilter(request, response);
+ }
+
+ /** {@inheritDoc} */
+ public void init(FilterConfig filterConfig) throws ServletException {
+ sessionManager = (SessionManager<Session>) filterConfig.getServletContext().getAttribute("sessionManager");
+ }
+
+ /**
+ * Gets the IdP session cookie from the current request, if the user currently has a session.
+ *
+ * @param request current HTTP request
+ *
+ * @return the user's current IdP session cookie, if they have a current session, otherwise null
+ */
+ protected Cookie getIdPSessionCookie(HttpServletRequest request) {
+ Cookie[] requestCookies = request.getCookies();
+
+ if (requestCookies != null) {
+ for (Cookie requestCookie : requestCookies) {
+ if (requestCookie.getDomain().equals(request.getLocalName())
+ && requestCookie.getPath().equals(request.getContextPath())
+ && requestCookie.getName().equalsIgnoreCase(IDP_SESSION_COOKIE_NAME)) {
+ return requestCookie;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Adds a cookie, containing the user's IdP session ID, to the response.
+ *
+ * @param request current HTTP request
+ * @param response current HTTP response
+ * @param userSession user's currentSession
+ */
+ protected void addIdPSessionCookieToResponse(HttpServletRequest request, HttpServletResponse response,
+ Session userSession) {
+ Cookie sessionCookie = new Cookie(IDP_SESSION_COOKIE_NAME, userSession.getSessionID());
+ sessionCookie.setDomain(request.getLocalName());
+ sessionCookie.setPath(request.getContextPath());
+ sessionCookie.setSecure(false);
+
+ int maxAge = (int) (userSession.getInactivityTimeout() / 1000);
+ sessionCookie.setMaxAge(maxAge);
+
+ response.addCookie(sessionCookie);
+ }
+}
\ No newline at end of file
*/
public interface Session extends edu.internet2.middleware.shibboleth.common.session.Session {
- /** Name of the HttpSession attribute a users Shibboleth session Id is bound to. */
- public static final String HTTP_SESSION_BINDING_ATTRIBUTE = "ShibbolethSessionId";
+ /** Name of the HttpSession attribute to which a users IdP session is bound. */
+ public static final String HTTP_SESSION_BINDING_ATTRIBUTE = "ShibbolethIdPSession";
/**
* Gets the methods by which the user has authenticated to the IdP.
package edu.internet2.middleware.shibboleth.idp.session.impl;
-import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
/** Serial version UID. */
private static final long serialVersionUID = 2927868242208211623L;
- /** The list of methods used to authentictate the user. */
+ /** The list of methods used to authenticate the user. */
private HashMap<String, AuthenticationMethodInformation> authnMethods;
/** The list of services to which the user has logged in. */
/**
* Default constructor.
*
- * @param presenter IP address of the presenter
+ * @param sessionId ID of the session
* @param principal principal ID of the user
+ * @param timeout inactivity timeout for the session in milliseconds
*/
- public SessionImpl(InetAddress presenter, String principal) {
- super(presenter, principal);
+ public SessionImpl(String sessionId, String principal, long timeout) {
+ super(sessionId, principal, timeout);
authnMethods = new HashMap<String, AuthenticationMethodInformation>();
servicesInformation = new HashMap<String, ServiceInformation>();
package edu.internet2.middleware.shibboleth.idp.session.impl;
-import java.net.InetAddress;
+import java.security.SecureRandom;
import org.joda.time.DateTime;
import org.opensaml.util.storage.ExpiringObject;
import org.opensaml.util.storage.StorageService;
+import org.opensaml.xml.util.Base64;
import org.opensaml.xml.util.DatatypeHelper;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/** Spring context used to publish login and logout events. */
private ApplicationContext appCtx;
+
+ /** Number of random bits within a session ID. */
+ private final int sessionIDSize = 32;
+
+ /** A {@link SecureRandom} PRNG to generate session IDs. */
+ private final SecureRandom prng = new SecureRandom();
/** Backing service used to store sessions. */
private StorageService<String, SessionManagerEntry> sessionStore;
}
/** {@inheritDoc} */
- public Session createSession(InetAddress presenter, String principal) {
- Session session = new SessionImpl(presenter, principal);
+ public Session createSession(String principal) {
+ // generate a random session ID
+ byte[] sid = new byte[sessionIDSize];
+ prng.nextBytes(sid);
+ String sessionID = Base64.encodeBytes(sid);
+
+ Session session = new SessionImpl(sessionID, principal, sessionLifetime);
SessionManagerEntry sessionEntry = new SessionManagerEntry(this, session, sessionLifetime);
sessionStore.put(partition, session.getSessionID(), sessionEntry);
appCtx.publishEvent(new LoginEvent(session));