https://bugs.internet2.edu/jira/browse/SIDP-281
authorlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Thu, 2 Jul 2009 18:32:32 +0000 (18:32 +0000)
committerlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Thu, 2 Jul 2009 18:32:32 +0000 (18:32 +0000)
https://bugs.internet2.edu/jira/browse/SIDP-324

git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/branches/REL_2@2860 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

doc/RELEASE-NOTES.txt
src/main/java/edu/internet2/middleware/shibboleth/idp/StatusServlet.java
src/main/java/edu/internet2/middleware/shibboleth/idp/authn/AuthenticationEngine.java
src/main/java/edu/internet2/middleware/shibboleth/idp/authn/provider/IPAddressLoginHandler.java
src/main/java/edu/internet2/middleware/shibboleth/idp/profile/saml1/ShibbolethSSOProfileHandler.java
src/main/java/edu/internet2/middleware/shibboleth/idp/profile/saml2/SSOProfileHandler.java
src/main/java/edu/internet2/middleware/shibboleth/idp/util/HttpServletHelper.java [new file with mode: 0644]
src/main/webapp/login.jsp

index 7acfeeb..6a5fd05 100644 (file)
@@ -1,21 +1,24 @@
 Changes in Release 2.1.3
 =============================================
+[SIDP-244] - Error message on invalid ACS could be improved
 [SIDP-247] - Log Exception in UP LoginHandler Servlet
 [SIDP-263] - Suggest adding defaultSigningCredentialRef to the AnonymousRelyingParty element in the default config
-[SIDP-261] - IPAddressLoginHandler addresses comparasion fails
+[SIDP-261] - IPAddressLoginHandler addresses comparison fails
 [SIDP-265] - Distinguish requested AuthMethod and default AuthMethod
 [SIDP-271] - AuthenticationEngine doesn't correctly handle passive return from login servlet
 [SIDP-276] - Example RDB Connector, quote principal
 [SIDP-277] - Incorrect null check for request context in UsernamePasswordServlet
 [SIDP-279] - IdP should log NameID for auditing
+[SIDP-281] - Customize login.jsp appearance based on relying party
 [SIDP-285] - Use $IDP_SCOPE$ to populate IdP scope in conf-tmpl\attribute-resolver.xml
 [SIDP-291] - Update libs for 2.1.3 release
-[SIDP-292] - login.jsp: wrong using of the attribute rawspan within the tag <td>
+[SIDP-292] - login.jsp: wrong using of the attribute rowspan within the tag <td>
 [SIDP-306] - Remove ClientCertAuth rule from SAML 2 SSO SecurityPolicy in relying-party.xml
 [SIDP-310] - Change default relying-party.xml settings for SAML 2 profiles' encryptNameIds parameter from "conditional" to "never"
 [SIDP-315] - Credential provided by UsernamePasswordLogin handler as attribute
 [SIDP-318] - IdP erroneously logs many normal events as errors
 [SIDP-322] - Exception thrown when SP requests a particular authentication method that is not configured
+[SIDP-324] - Add additional information to Status handler
 
 Changes in Release 2.1.2
 =============================================
index e092b3d..a63cdfb 100644 (file)
@@ -29,16 +29,21 @@ import org.joda.time.DateTime;
 import org.joda.time.chrono.ISOChronology;
 import org.joda.time.format.DateTimeFormatter;
 import org.joda.time.format.ISODateTimeFormat;
-import org.opensaml.xml.util.DatatypeHelper;
+import org.opensaml.xml.security.x509.X509Credential;
+import org.opensaml.xml.util.Base64;
 
 import edu.internet2.middleware.shibboleth.common.attribute.resolver.AttributeResolutionException;
 import edu.internet2.middleware.shibboleth.common.attribute.resolver.AttributeResolver;
 import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfiguration;
 import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfigurationManager;
+import edu.internet2.middleware.shibboleth.idp.util.HttpServletHelper;
 
-/** A servlet for displaying the status of the IdP. */
+/** A Servlet for displaying the status of the IdP. */
 public class StatusServlet extends HttpServlet {
 
+    /** Serial version UID. */
+    private static final long serialVersionUID = 7917509317276109266L;
+
     /** Formatter used when print date/times. */
     private DateTimeFormatter dateFormat;
 
@@ -56,24 +61,14 @@ public class StatusServlet extends HttpServlet {
         super.init(config);
 
         dateFormat = ISODateTimeFormat.dateTimeNoMillis();
-
         startTime = new DateTime(ISOChronology.getInstanceUTC());
-
-        String attributeResolverId = config.getInitParameter("attributeResolverId");
-        if (DatatypeHelper.isEmpty(attributeResolverId)) {
-            attributeResolverId = "shibboleth.AttributeResolver";
-        }
-        attributeResolver = (AttributeResolver<?>) getServletContext().getAttribute(attributeResolverId);
-
-        String rpConfigManagerId = config.getInitParameter("rpConfigManagerId");
-        if (DatatypeHelper.isEmpty(rpConfigManagerId)) {
-            rpConfigManagerId = "shibboleth.RelyingPartyConfigurationManager";
-        }
-        rpConfigManager = (RelyingPartyConfigurationManager) getServletContext().getAttribute(rpConfigManagerId);
+        attributeResolver = HttpServletHelper.getAttributeResolver(config.getServletContext());
+        rpConfigManager = HttpServletHelper.getRelyingPartyConfirmationManager(config.getServletContext());
     }
 
     /** {@inheritDoc} */
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        resp.setContentType("text/plain");
         PrintWriter output = resp.getWriter();
 
         printOperatingEnvironmentInformation(output);
@@ -160,13 +155,20 @@ public class StatusServlet extends HttpServlet {
     protected void printRelyingPartyConfigurationInformation(PrintWriter out, RelyingPartyConfiguration config) {
         out.println("relying_party_id: " + config.getRelyingPartyId());
         out.println("idp_entity_id: " + config.getProviderId());
-
+        
         if (config.getDefaultAuthenticationMethod() != null) {
             out.println("default_authentication_method: " + config.getDefaultAuthenticationMethod());
         } else {
             out.println("default_authentication_method: none");
         }
 
+        try{
+            X509Credential signingCredential = (X509Credential) config.getDefaultSigningCredential();
+            out.println("default_signing_tls_key: " + Base64.encodeBytes(signingCredential.getEntityCertificate().getEncoded(), Base64.DONT_BREAK_LINES));
+        }catch(Throwable t){
+            // swallow error
+        }
+        
         for (String profileId : config.getProfileConfigurations().keySet()) {
             out.println("configured_communication_profile: " + profileId);
         }
index ce37b8f..300ee22 100644 (file)
@@ -19,7 +19,6 @@ package edu.internet2.middleware.shibboleth.idp.authn;
 import java.io.IOException;
 import java.security.GeneralSecurityException;
 import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
 import java.security.Principal;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -32,6 +31,7 @@ import java.util.Map.Entry;
 import javax.security.auth.Subject;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServlet;
@@ -39,8 +39,6 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.joda.time.DateTime;
-import org.opensaml.common.IdentifierGenerator;
-import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
 import org.opensaml.saml2.core.AuthnContext;
 import org.opensaml.util.storage.StorageService;
 import org.opensaml.ws.transport.http.HTTPTransportUtils;
@@ -57,6 +55,7 @@ import edu.internet2.middleware.shibboleth.idp.session.ServiceInformation;
 import edu.internet2.middleware.shibboleth.idp.session.Session;
 import edu.internet2.middleware.shibboleth.idp.session.impl.AuthenticationMethodInformationImpl;
 import edu.internet2.middleware.shibboleth.idp.session.impl.ServiceInformationImpl;
+import edu.internet2.middleware.shibboleth.idp.util.HttpServletHelper;
 
 /** Manager responsible for handling authentication requests. */
 public class AuthenticationEngine extends HttpServlet {
@@ -90,19 +89,13 @@ public class AuthenticationEngine extends HttpServlet {
 
     /** Class logger. */
     private static final Logger LOG = LoggerFactory.getLogger(AuthenticationEngine.class);
+    
+    //TODO remove once HttpServletHelper does redirects
+    private static ServletContext context;
 
     /** Storage service used to store {@link LoginContext}s while authentication is in progress. */
     private static StorageService<String, LoginContextEntry> storageService;
 
-    /** Name of the storage service partition used to store login contexts. */
-    private static String loginContextPartitionName;
-
-    /** Lifetime of stored login contexts. */
-    private static long loginContextEntryLifetime;
-
-    /** ID generator. */
-    private static IdentifierGenerator idGen;
-
     /** Whether the public credentials of a {@link Subject} are retained after authentication. */
     private boolean retainSubjectsPublicCredentials;
 
@@ -133,100 +126,11 @@ public class AuthenticationEngine extends HttpServlet {
             retainSubjectsPublicCredentials = false;
         }
 
-        String handlerManagerId = config.getInitParameter("handlerManagerId");
-        if (DatatypeHelper.isEmpty(handlerManagerId)) {
-            handlerManagerId = "shibboleth.HandlerManager";
-        }
-        handlerManager = (IdPProfileHandlerManager) getServletContext().getAttribute(handlerManagerId);
-
-        String sessionManagerId = config.getInitParameter("sessionManagedId");
-        if (DatatypeHelper.isEmpty(sessionManagerId)) {
-            sessionManagerId = "shibboleth.SessionManager";
-        }
-        sessionManager = (SessionManager<Session>) getServletContext().getAttribute(sessionManagerId);
-
-        String storageServiceId = config.getInitParameter("storageServiceId");
-        if (DatatypeHelper.isEmpty(storageServiceId)) {
-            storageServiceId = "shibboleth.StorageService";
-        }
-        storageService = (StorageService<String, LoginContextEntry>) getServletContext().getAttribute(storageServiceId);
-
-        String partitionName = DatatypeHelper.safeTrimOrNullString(config
-                .getInitParameter(LOGIN_CONTEXT_PARTITION_NAME_INIT_PARAM_NAME));
-        if (partitionName != null) {
-            loginContextPartitionName = partitionName;
-        } else {
-            loginContextPartitionName = "loginContexts";
-        }
-
-        String lifetime = DatatypeHelper.safeTrimOrNullString(config
-                .getInitParameter(LOGIN_CONTEXT_LIFETIME_INIT_PARAM_NAME));
-        if (lifetime != null) {
-            loginContextEntryLifetime = Long.parseLong(lifetime);
-        } else {
-            loginContextEntryLifetime = 1000 * 60 * 30;
-        }
-
-        try {
-            idGen = new SecureRandomIdentifierGenerator();
-        } catch (NoSuchAlgorithmException e) {
-            throw new ServletException("Error create random number generator", e);
-        }
-    }
-
-    /**
-     * Retrieves a login context.
-     * 
-     * @param httpRequest current HTTP request
-     * @param removeFromStorageService whether the login context should be removed from the storage service as it is
-     *            retrieved
-     * 
-     * @return the login context or null if one is not available (e.g. because it has expired)
-     */
-    protected static LoginContext retrieveLoginContext(HttpServletRequest httpRequest, boolean removeFromStorageService) {
-        // When the login context comes from the profile handlers its attached to the request
-        // Prior to the authentication engine handing control over to a login handler it stores
-        // the login context into the storage service so that the login handlers do not have to
-        // maintain a reference to the context and return it to the engine.
-        LoginContext loginContext = (LoginContext) httpRequest.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
-        if (loginContext != null) {
-            LOG.trace("Login context retrieved from HTTP request attribute");
-            return loginContext;
-        }
-
-        String contextId = DatatypeHelper.safeTrimOrNullString((String) httpRequest
-                .getAttribute(LOGIN_CONTEXT_KEY_NAME));
-
-        if (contextId == null) {
-            Cookie[] requestCookies = httpRequest.getCookies();
-            if (requestCookies != null) {
-                for (Cookie requestCookie : requestCookies) {
-                    if (DatatypeHelper.safeEquals(requestCookie.getName(), LOGIN_CONTEXT_KEY_NAME)) {
-                        LOG.trace("Located cookie with login context key");
-                        contextId = requestCookie.getValue();
-                        break;
-                    }
-                }
-            }
-        }
-
-        LOG.trace("Using login context key {} to look up login context", contextId);
-        LoginContextEntry entry;
-        if (removeFromStorageService) {
-            entry = storageService.remove(loginContextPartitionName, contextId);
-        } else {
-            entry = storageService.get(loginContextPartitionName, contextId);
-        }
-        if (entry == null) {
-            LOG.trace("No entry for login context found in storage service.");
-            return null;
-        } else if (entry.isExpired()) {
-            LOG.trace("Login context entry found in storage service but it was expired.");
-            return null;
-        } else {
-            LOG.trace("Login context entry found in storage service.");
-            return entry.getLoginContext();
-        }
+        handlerManager = HttpServletHelper.getProfileHandlerManager(config.getServletContext());
+        sessionManager = HttpServletHelper.getSessionManager(config.getServletContext());
+        storageService = (StorageService<String, LoginContextEntry>) HttpServletHelper.getStorageService(config.getServletContext());
+        
+        context = config.getServletContext();
     }
 
     /**
@@ -237,7 +141,7 @@ public class AuthenticationEngine extends HttpServlet {
      */
     public static void returnToAuthenticationEngine(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
         LOG.debug("Returning control to authentication engine");
-        LoginContext loginContext = retrieveLoginContext(httpRequest, false);
+        LoginContext loginContext = HttpServletHelper.getLoginContext(storageService, context, httpRequest);
         if (loginContext == null) {
             LOG.warn("No login context available, unable to return to authentication engine");
             forwardRequest("/idp-error.jsp", httpRequest, httpResponse);
@@ -253,16 +157,17 @@ public class AuthenticationEngine extends HttpServlet {
      * @param httpRequest current HTTP request
      * @param httpResponse current HTTP response
      */
-    public static void returnToProfileHandler(LoginContext loginContext, HttpServletRequest httpRequest,
+    public static void returnToProfileHandler(HttpServletRequest httpRequest,
             HttpServletResponse httpResponse) {
+        LOG.debug("Returning control to login handler");
+        LoginContext loginContext = HttpServletHelper.unbindLoginContext(storageService, context, httpRequest, httpResponse);
+        if (loginContext == null) {
+            LOG.warn("No login context available, unable to return to profile handler");
+            forwardRequest("/idp-error.jsp", httpRequest, httpResponse);
+        }
+        
+        HttpServletHelper.bindLoginContext(loginContext, httpRequest);
         LOG.debug("Returning control to profile handler at: {}", loginContext.getProfileHandlerURL());
-        httpRequest.setAttribute(LoginContext.LOGIN_CONTEXT_KEY, loginContext);
-
-        // Cleanup this cookie
-        Cookie lcKeyCookie = new Cookie(LOGIN_CONTEXT_KEY_NAME, "");
-        lcKeyCookie.setMaxAge(0);
-        httpResponse.addCookie(lcKeyCookie);
-
         forwardRequest(loginContext.getProfileHandlerURL(), httpRequest, httpResponse);
     }
 
@@ -296,7 +201,7 @@ public class AuthenticationEngine extends HttpServlet {
             LOG.error("HTTP Response already committed");
         }
 
-        LoginContext loginContext = retrieveLoginContext(httpRequest, true);
+        LoginContext loginContext = HttpServletHelper.getLoginContext(storageService, getServletContext(), httpRequest);
         if (loginContext == null) {
             LOG.error("Incoming request does not have attached login context");
             throw new ServletException("Incoming request does not have attached login context");
@@ -365,15 +270,16 @@ public class AuthenticationEngine extends HttpServlet {
                 }
             }
 
-            // Send the request to the login handler
             LOG.debug("Authenticating user with login handler of type {}", loginHandler.getClass().getName());
             loginContext.setAuthenticationAttempted();
             loginContext.setAuthenticationEngineURL(HttpHelper.getRequestUriWithoutContext(httpRequest));
-            storeLoginContext(loginContext, httpRequest, httpResponse);
+            
+            // Send the request to the login handler
+            HttpServletHelper.bindLoginContext(loginContext, storageService, getServletContext(), httpRequest, httpResponse);
             loginHandler.login(httpRequest, httpResponse);
         } catch (AuthenticationException e) {
             loginContext.setAuthenticationFailure(e);
-            returnToProfileHandler(loginContext, httpRequest, httpResponse);
+            returnToProfileHandler(httpRequest, httpResponse);
         }
     }
 
@@ -522,35 +428,6 @@ public class AuthenticationEngine extends HttpServlet {
     }
 
     /**
-     * Stores the login context in the storage service. The key for the stored login context is then bound to an HTTP
-     * request attribute and set a cookie.
-     * 
-     * @param loginContext login context to store
-     * @param httpRequest current HTTP request
-     * @param httpResponse current HTTP response
-     */
-    protected void storeLoginContext(LoginContext loginContext, HttpServletRequest httpRequest,
-            HttpServletResponse httpResponse) {
-        String contextId = idGen.generateIdentifier();
-
-        storageService.put(loginContextPartitionName, contextId, new LoginContextEntry(loginContext,
-                loginContextEntryLifetime));
-
-        httpRequest.setAttribute(LOGIN_CONTEXT_KEY_NAME, contextId);
-
-        Cookie cookie = new Cookie(LOGIN_CONTEXT_KEY_NAME, contextId);
-        String contextPath = httpRequest.getContextPath();
-        if (DatatypeHelper.isEmpty(contextPath)) {
-            cookie.setPath("/");
-        } else {
-            cookie.setPath(contextPath);
-        }
-        cookie.setSecure(httpRequest.isSecure());
-        cookie.setMaxAge(-1);
-        httpResponse.addCookie(cookie);
-    }
-
-    /**
      * Completes the authentication process.
      * 
      * The principal name set by the authentication handler is retrieved and pushed in to the login context, a
@@ -599,7 +476,7 @@ public class AuthenticationEngine extends HttpServlet {
             loginContext.setAuthenticationFailure(e);
         }
 
-        returnToProfileHandler(loginContext, httpRequest, httpResponse);
+        returnToProfileHandler(httpRequest, httpResponse);
     }
 
     /**
index 7323d58..d6f316e 100644 (file)
@@ -48,9 +48,6 @@ public class IPAddressLoginHandler extends AbstractLoginHandler {
     /** Class logger. */
     private final Logger log = LoggerFactory.getLogger(IPAddressLoginHandler.class);
 
-    /** The URI of the AuthnContextDeclRef or the AuthnContextClass. */
-    private String authnMethodURI = "urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol";
-
     /** The username to use for IP-address "authenticated" users. */
     private String username;
 
index 0e90415..d413966 100644 (file)
@@ -61,6 +61,7 @@ import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml1.Sh
 import edu.internet2.middleware.shibboleth.common.util.HttpHelper;
 import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
 import edu.internet2.middleware.shibboleth.idp.authn.ShibbolethSSOLoginContext;
+import edu.internet2.middleware.shibboleth.idp.util.HttpServletHelper;
 
 /** Shibboleth SSO request profile handler. */
 public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
@@ -114,7 +115,7 @@ public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
         log.debug("Processing incoming request");
 
         HttpServletRequest httpRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
-        LoginContext loginContext = (LoginContext) httpRequest.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
+        LoginContext loginContext = HttpServletHelper.getLoginContext(httpRequest);
 
         if (loginContext == null) {
             log.debug("Incoming request does not contain a login context, processing as first leg of request");
@@ -149,19 +150,20 @@ public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
         loginContext.setDefaultAuthenticationMethod(rpConfig.getDefaultAuthenticationMethod());
         ProfileConfiguration ssoConfig = rpConfig.getProfileConfiguration(ShibbolethSSOConfiguration.PROFILE_ID);
         if (ssoConfig == null) {
-            String msg = MessageFormatter.format("Shibboleth SSO profile is not configured for relying party '{}'", loginContext.getRelyingPartyId());
+            String msg = MessageFormatter.format("Shibboleth SSO profile is not configured for relying party '{}'",
+                    loginContext.getRelyingPartyId());
             log.warn(msg);
             throw new ProfileException(msg);
         }
 
-        httpRequest.setAttribute(LoginContext.LOGIN_CONTEXT_KEY, loginContext);
+        HttpServletHelper.bindLoginContext(loginContext, httpRequest);
 
         try {
             RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(authenticationManagerPath);
             dispatcher.forward(httpRequest, httpResponse);
             return;
         } catch (IOException e) {
-            String msg = "Error forwarding Shibboleth SSO request to AuthenticationManager"; 
+            String msg = "Error forwarding Shibboleth SSO request to AuthenticationManager";
             log.error(msg, e);
             throw new ProfileException(msg, e);
         } catch (ServletException e) {
@@ -203,9 +205,10 @@ public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
         requestContext.setMessageDecoder(decoder);
         try {
             decoder.decode(requestContext);
-            log.debug("Decoded Shibboleth SSO request from relying party '{}'", requestContext.getInboundMessageIssuer());
+            log.debug("Decoded Shibboleth SSO request from relying party '{}'", requestContext
+                    .getInboundMessageIssuer());
         } catch (MessageDecodingException e) {
-            String msg = "Error decoding Shibboleth SSO request"; 
+            String msg = "Error decoding Shibboleth SSO request";
             log.warn(msg, e);
             throw new ProfileException(msg, e);
         } catch (SecurityException e) {
@@ -235,8 +238,7 @@ public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
     protected void completeAuthenticationRequest(HTTPInTransport inTransport, HTTPOutTransport outTransport)
             throws ProfileException {
         HttpServletRequest httpRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
-        ShibbolethSSOLoginContext loginContext = (ShibbolethSSOLoginContext) httpRequest
-                .getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
+        ShibbolethSSOLoginContext loginContext = (ShibbolethSSOLoginContext) HttpServletHelper.getLoginContext(httpRequest);
 
         ShibbolethSSORequestContext requestContext = buildRequestContext(loginContext, inTransport, outTransport);
 
index 952e17e..3eb7e2b 100644 (file)
@@ -74,6 +74,7 @@ import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
 import edu.internet2.middleware.shibboleth.idp.authn.PassiveAuthenticationException;
 import edu.internet2.middleware.shibboleth.idp.authn.Saml2LoginContext;
 import edu.internet2.middleware.shibboleth.idp.session.Session;
+import edu.internet2.middleware.shibboleth.idp.util.HttpServletHelper;
 
 /** SAML 2.0 SSO request profile handler. */
 public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
@@ -99,13 +100,13 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
     /** Builder of Endpoint objects. */
     private SAMLObjectBuilder<Endpoint> endpointBuilder;
 
-    /** URL of the authentication manager servlet. */
+    /** URL of the authentication manager Servlet. */
     private String authenticationManagerPath;
 
     /**
      * Constructor.
      * 
-     * @param authnManagerPath path to the authentication manager servlet
+     * @param authnManagerPath path to the authentication manager Servlet
      */
     @SuppressWarnings("unchecked")
     public SSOProfileHandler(String authnManagerPath) {
@@ -134,9 +135,9 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
 
     /** {@inheritDoc} */
     public void processRequest(HTTPInTransport inTransport, HTTPOutTransport outTransport) throws ProfileException {
-        HttpServletRequest servletRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
+        HttpServletRequest httpRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
 
-        LoginContext loginContext = (LoginContext) servletRequest.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
+        LoginContext loginContext = HttpServletHelper.getLoginContext(httpRequest);
         if (loginContext == null) {
             log.debug("Incoming request does not contain a login context, processing as first leg of request");
             performAuthentication(inTransport, outTransport);
@@ -180,7 +181,7 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
             loginContext.setProfileHandlerURL(HttpHelper.getRequestUriWithoutContext(servletRequest));
             loginContext.setDefaultAuthenticationMethod(rpConfig.getDefaultAuthenticationMethod());
             
-            servletRequest.setAttribute(Saml2LoginContext.LOGIN_CONTEXT_KEY, loginContext);
+            HttpServletHelper.bindLoginContext(loginContext, servletRequest);
             RequestDispatcher dispatcher = servletRequest.getRequestDispatcher(authenticationManagerPath);
             dispatcher.forward(servletRequest, ((HttpServletResponseAdapter) outTransport).getWrappedResponse());
         } catch (MarshallingException e) {
@@ -206,10 +207,9 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
      */
     protected void completeAuthenticationRequest(HTTPInTransport inTransport, HTTPOutTransport outTransport)
             throws ProfileException {
-        HttpServletRequest servletRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
-
-        Saml2LoginContext loginContext = (Saml2LoginContext) servletRequest
-                .getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
+        HttpServletRequest httpRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
+        Saml2LoginContext loginContext = (Saml2LoginContext) HttpServletHelper.getLoginContext(httpRequest);
+        
         SSORequestContext requestContext = buildRequestContext(loginContext, inTransport, outTransport);
 
         checkSamlVersion(requestContext);
diff --git a/src/main/java/edu/internet2/middleware/shibboleth/idp/util/HttpServletHelper.java b/src/main/java/edu/internet2/middleware/shibboleth/idp/util/HttpServletHelper.java
new file mode 100644 (file)
index 0000000..aebbbf0
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+ * Copyright 2009 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.util;
+
+import java.util.UUID;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.opensaml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.opensaml.util.storage.StorageService;
+import org.opensaml.xml.util.DatatypeHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import edu.internet2.middleware.shibboleth.common.attribute.filtering.AttributeFilteringEngine;
+import edu.internet2.middleware.shibboleth.common.attribute.provider.SAML1AttributeAuthority;
+import edu.internet2.middleware.shibboleth.common.attribute.provider.SAML2AttributeAuthority;
+import edu.internet2.middleware.shibboleth.common.attribute.resolver.AttributeResolver;
+import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfigurationManager;
+import edu.internet2.middleware.shibboleth.common.relyingparty.provider.SAMLMDRelyingPartyConfigurationManager;
+import edu.internet2.middleware.shibboleth.common.session.SessionManager;
+import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
+import edu.internet2.middleware.shibboleth.idp.authn.LoginContextEntry;
+import edu.internet2.middleware.shibboleth.idp.profile.IdPProfileHandlerManager;
+import edu.internet2.middleware.shibboleth.idp.session.Session;
+
+/** A helper class that provides access to internal state from Servlets and hence also JSPs. */
+public class HttpServletHelper {
+
+    /** Name of the cookie containing the IdP session ID: {@value} . */
+    public static final String IDP_SESSION_COOKIE = "_idp_session";
+
+    /** Name of the key to the current authentication login context: {@value} . */
+    public static final String LOGIN_CTX_KEY_NAME = "_idp_authn_lc_key";
+
+    /** {@link ServletContext} parameter name bearing the ID of the {@link AttributeFilteringEngine} service: {@value} . */
+    public static final String ATTRIBUTE_FILTER_ENGINE_SID_CTX_PARAM = "AttributeFilterEngineId";
+
+    /** {@link ServletContext} parameter name bearing the ID of the {@link AttributeResolver} service: {@value} . */
+    public static final String ATTRIBUTE_RESOLVER_SID_CTX_PARAM = "AttributeResolverId";
+
+    /**
+     * {@link ServletContext} parameter name bearing the name of the {@link StorageService} partition into which
+     * {@link LoginContext}s are stored: {@value} .
+     */
+    public static final String LOGIN_CTX_PARTITION_CTX_PARAM = "loginContextPartitionName";
+
+    /** {@link ServletContext} parameter name bearing the ID of the {@link IdPProfileHandlerManager} service: {@value} . */
+    public static final String PROFILE_HANDLER_MNGR_SID_CTX_PARAM = "ProfileHandlerMngrId";
+
+    /**
+     * {@link ServletContext} parameter name bearing the ID of the {@link RelyingPartyConfigurationManager} service: * *
+     * * {@value} .
+     */
+    public static final String RP_CONFIG_MNGR_SID_CTX_PARAM = "RelyingPartyConfigurationManagerId";
+
+    /** {@link ServletContext} parameter name bearing the ID of the {@link SAML1AttributeAuthority} service: {@value} . */
+    public static final String SAML1_AA_SID_CTX_PARAM = "SAML1AttributeAuthorityId";
+
+    /** {@link ServletContext} parameter name bearing the ID of the {@link SAML2AttributeAuthority} service: {@value} . */
+    public static final String SAML2_AA_SID_CTX_PARAM = "SAML2AttributeAuthorityId";
+
+    /** {@link ServletContext} parameter name bearing the ID of the {@link SessionManager} service: {@value} . */
+    public static final String SESSION_MNGR_SID_CTX_PARAM = "SessionManagerId";
+
+    /** {@link ServletContext} parameter name bearing the ID of the {@link SAML1AttributeAuthority} service: {@value} . */
+    public static final String STORAGE_SERVICE_SID_CTX_PARAM = "StorageServiceId";
+
+    /** Default ID by which the {@link AttributeFilteringEngine} is know within the Servlet context: {@value} . */
+    public static final String DEFAULT_ATTRIBUTE_FILTER_ENGINE_SID = "shibboleth.AttributeFilterEngine";
+
+    /** Default ID by which the {@link AttributeResolver} is know within the Servlet context: {@value} . */
+    public static final String DEFAULT_ATTRIBUTE_RESOLVER_SID = "shibboleth.AttributeResolver";
+
+    /** Default name for the {@link StorageService} partition which holds {@link LoginContext}s: {@value} . */
+    public static final String DEFAULT_LOGIN_CTX_PARITION = "loginContexts";
+
+    /** Default ID by which the {@link IdPProfileHandlerManager} is know within the Servlet context: {@value} . */
+    public static final String DEFAULT_PROFILE_HANDLER_MNGR_SID = "shibboleth.HandlerManager";
+
+    /** Default ID by which the {@link RelyingPartyConfigurationManager} is know within the Servlet context: {@value} . */
+    public static final String DEFAULT_RP_CONFIG_MNGR_SID = "shibboleth.RelyingPartyConfigurationManager";
+
+    /** Default ID by which the {@link SAML1AttributeAuthority} is know within the Servlet context: {@value} . */
+    public static final String DEFAULT_SAML1_AA_SID = "shibboleth.SAML1AttributeAuthority";
+
+    /** Default ID by which the {@link SAML2AttributeAuthority} is know within the Servlet context: {@value} . */
+    public static final String DEFAULT_SAML2_AA_SID = "shibboleth.SAML2AttributeAuthority";
+
+    /** Default ID by which the {@link SessionManager} is know within the Servlet context: {@value} . */
+    public static final String DEFAULT_SESSION_MNGR_SID = "shibboleth.SessionManager";
+
+    /** Default ID by which the {@link StorageService} is know within the Servlet context: {@value} . */
+    public static final String DEFAULT_STORAGE_SERVICE_SID = "shibboleth.StorageService";
+
+    /** Class logger. */
+    private static final Logger log = LoggerFactory.getLogger(HttpServletHelper.class);
+
+    /**
+     * Binds a {@link LoginContext} to the current request.
+     * 
+     * @param loginContext login context to be bound
+     * @param request current HTTP request
+     */
+    public static void bindLoginContext(LoginContext loginContext, HttpServletRequest request) {
+        if (request == null) {
+            throw new IllegalArgumentException("HTTP request may not be null");
+        }
+        request.setAttribute(LOGIN_CTX_KEY_NAME, loginContext);
+    }
+
+    /**
+     * Binds a {@link LoginContext} to the issuer of the current request. The binding is done by creating a random UUID,
+     * placing that in a cookie in the request, and storing the context in to the storage service under that key.
+     * 
+     * @param loginContext the login context to be bound
+     * @param storageService the storage service which will hold the context
+     * @param context the Servlet context
+     * @param httpRequest the current HTTP request
+     * @param httpResponse the current HTTP response
+     */
+    public static void bindLoginContext(LoginContext loginContext,
+            StorageService storageService, ServletContext context,
+            HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
+        if (storageService == null) {
+            throw new IllegalArgumentException("Storage service may not be null");
+        }
+        if (httpRequest == null) {
+            throw new IllegalArgumentException("HTTP request may not be null");
+        }
+        if (loginContext == null) {
+            return;
+        }
+
+        String parition = getContextParam(context, LOGIN_CTX_PARTITION_CTX_PARAM, DEFAULT_LOGIN_CTX_PARITION);
+        log.debug("LoginContext parition: {}", parition);
+
+        String contextKey = UUID.randomUUID().toString();
+        while (storageService.contains(parition, contextKey)) {
+            contextKey = UUID.randomUUID().toString();
+        }
+        log.debug("LoginContext key: {}", contextKey);
+
+        LoginContextEntry entry = new LoginContextEntry(loginContext, 1800000);
+        storageService.put(parition, contextKey, entry);
+
+        Cookie contextKeyCookie = new Cookie(LOGIN_CTX_KEY_NAME, contextKey);
+        contextKeyCookie.setPath("/");
+        contextKeyCookie.setSecure(httpRequest.isSecure());
+        contextKeyCookie.setMaxAge(31556926);
+        httpResponse.addCookie(contextKeyCookie);
+    }
+
+    /**
+     * Gets the {@link AttributeFilteringEngine} service bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static AttributeFilteringEngine<?> getAttributeFilterEnginer(ServletContext context) {
+        return getAttributeFilterEnginer(context, getContextParam(context, ATTRIBUTE_FILTER_ENGINE_SID_CTX_PARAM,
+                DEFAULT_ATTRIBUTE_FILTER_ENGINE_SID));
+    }
+
+    /**
+     * Gets the {@link AttributeFilteringEngine} bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * @param serviceId the ID under which the service bound
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static AttributeFilteringEngine<?> getAttributeFilterEnginer(ServletContext context, String serviceId) {
+        return (AttributeFilteringEngine<?>) context.getAttribute(serviceId);
+    }
+
+    /**
+     * Gets the {@link AttributeResolver} service bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static AttributeResolver<?> getAttributeResolver(ServletContext context) {
+        return getAttributeResolver(context, getContextParam(context, ATTRIBUTE_RESOLVER_SID_CTX_PARAM,
+                DEFAULT_ATTRIBUTE_RESOLVER_SID));
+    }
+
+    /**
+     * Gets the {@link AttributeResolver} bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * @param serviceId the ID under which the service bound
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static AttributeResolver<?> getAttributeResolver(ServletContext context, String serviceId) {
+        return (AttributeResolver<?>) context.getAttribute(serviceId);
+    }
+
+    /**
+     * Gets a value for a given context parameter. If no value is present the default value is used.
+     * 
+     * @param context the Servlet context
+     * @param name name of the context parameter
+     * @param defaultValue default value of the parameter
+     * 
+     * @return the value of the context parameter or the default value if the parameter is not set or does not contain a
+     *         value
+     */
+    public static String getContextParam(ServletContext context, String name, String defaultValue) {
+        String value = DatatypeHelper.safeTrimOrNullString(context.getInitParameter(name));
+        if (value == null) {
+            value = defaultValue;
+        }
+        return value;
+    }
+
+    /**
+     * Gets the first {@link Cookie} whose name matches the given name.
+     * 
+     * @param cookieName the cookie name
+     * @param httpRequest HTTP request from which the cookie should be extracted
+     * 
+     * @return the cookie or null if no cookie with that name was given
+     */
+    public static Cookie getCookie(HttpServletRequest httpRequest, String cookieName) {
+        Cookie[] requestCookies = httpRequest.getCookies();
+        if (requestCookies != null) {
+            for (Cookie requestCookie : requestCookies) {
+                if (requestCookie != null && DatatypeHelper.safeEquals(requestCookie.getName(), cookieName)) {
+                    return requestCookie;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Gets the login context from the current request. The login context is only in this location while the request is
+     * being transferred from the authentication engine back to the profile handler.
+     * 
+     * @param httpRequest current HTTP request
+     * 
+     * @return the login context or null if no login context is bound to the request
+     */
+    public static LoginContext getLoginContext(HttpServletRequest httpRequest) {
+        return (LoginContext) httpRequest.getAttribute(LOGIN_CTX_KEY_NAME);
+    }
+
+    /**
+     * Gets the {@link LoginContext} for the user issuing the HTTP request. Note, login contexts are only available
+     * during the authentication process.
+     * 
+     * @param context the Servlet context
+     * @param storageService storage service to use when retrieving the login context
+     * @param httpRequest current HTTP request
+     * 
+     * @return the login context or null if none is available
+     */
+    public static LoginContext getLoginContext(StorageService storageService,
+            ServletContext context, HttpServletRequest httpRequest) {
+        if (storageService == null) {
+            throw new IllegalArgumentException("Storage service may not be null");
+        }
+        if (context == null) {
+            throw new IllegalArgumentException("Servlet context may not be null");
+        }
+        if (httpRequest == null) {
+            throw new IllegalArgumentException("HTTP request may not be null");
+        }
+
+        LoginContext loginContext = getLoginContext(httpRequest);
+        if (loginContext == null) {
+            log.debug("LoginContext not bound to HTTP request, retrieving it from storage service");
+            Cookie loginContextKeyCookie = getCookie(httpRequest, LOGIN_CTX_KEY_NAME);
+            if (loginContextKeyCookie == null) {
+                log.debug("LoginContext key cookie was not present in request");
+                return null;
+            }
+
+            String loginContextKey = DatatypeHelper.safeTrimOrNullString(loginContextKeyCookie.getValue());
+            if (loginContextKey == null) {
+                log.warn("Corrupted LoginContext Key cookie, it did not contain a value");
+            }
+            log.debug("LoginContext key is '{}'", loginContextKey);
+
+            String partition = getContextParam(context, LOGIN_CTX_PARTITION_CTX_PARAM, DEFAULT_LOGIN_CTX_PARITION);
+            log.debug("parition: {}", partition);
+            LoginContextEntry entry = (LoginContextEntry) storageService.get(partition, loginContextKey);
+            if (entry != null) {
+                if (entry.isExpired()) {
+                    log.debug("LoginContext found but it was expired");
+                } else {
+                    loginContext = entry.getLoginContext();
+                }
+            } else {
+                log.debug("No login context in storage service");
+            }
+        }
+
+        return loginContext;
+    }
+
+    /**
+     * Gets the {@link IdPProfileHandlerManager} service bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static IdPProfileHandlerManager getProfileHandlerManager(ServletContext context) {
+        return getProfileHandlerManager(context, getContextParam(context, PROFILE_HANDLER_MNGR_SID_CTX_PARAM,
+                DEFAULT_PROFILE_HANDLER_MNGR_SID));
+    }
+
+    /**
+     * Gets the {@link IdPProfileHandlerManager} bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * @param serviceId the ID under which the service bound
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static IdPProfileHandlerManager getProfileHandlerManager(ServletContext context, String serviceId) {
+        return (IdPProfileHandlerManager) context.getAttribute(serviceId);
+    }
+
+    /**
+     * Gets the {@link RelyingPartyConfigurationManager} service bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static RelyingPartyConfigurationManager getRelyingPartyConfirmationManager(ServletContext context) {
+        return getRelyingPartyConfirmationManager(context, getContextParam(context, RP_CONFIG_MNGR_SID_CTX_PARAM,
+                DEFAULT_RP_CONFIG_MNGR_SID));
+    }
+
+    /**
+     * Gets the {@link RelyingPartyConfigurationManager} bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * @param serviceId the ID under which the service bound
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static RelyingPartyConfigurationManager getRelyingPartyConfirmationManager(ServletContext context,
+            String serviceId) {
+        return (RelyingPartyConfigurationManager) context.getAttribute(serviceId);
+    }
+
+    /**
+     * Gets the metatdata for a given relying party.
+     * 
+     * @param relyingPartyEntityId the ID of the relying party
+     * @param rpConfigMngr relying party configuration manager
+     * 
+     * @return the metadata for the relying party or null if no SAML metadata exists for the given relying party
+     */
+    public static EntityDescriptor getRelyingPartyMetadata(String relyingPartyEntityId,
+            RelyingPartyConfigurationManager rpConfigMngr) {
+        if (rpConfigMngr instanceof SAMLMDRelyingPartyConfigurationManager) {
+            SAMLMDRelyingPartyConfigurationManager samlRpConfigMngr = (SAMLMDRelyingPartyConfigurationManager) rpConfigMngr;
+            try {
+                return samlRpConfigMngr.getMetadataProvider().getEntityDescriptor(relyingPartyEntityId);
+            } catch (MetadataProviderException e) {
+
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Gets the {@link SAML1AttributeAuthority} service bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static SAML1AttributeAuthority getSAML1AttributeAuthority(ServletContext context) {
+        return getSAML1AttributeAuthority(context, getContextParam(context, SAML1_AA_SID_CTX_PARAM,
+                DEFAULT_SAML1_AA_SID));
+    }
+
+    /**
+     * Gets the {@link SAML1AttributeAuthority} bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * @param serviceId the ID under which the service bound
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static SAML1AttributeAuthority getSAML1AttributeAuthority(ServletContext context, String serviceId) {
+        return (SAML1AttributeAuthority) context.getAttribute(serviceId);
+    }
+
+    /**
+     * Gets the {@link SAML2AttributeAuthority} service bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static SAML2AttributeAuthority getSAML2AttributeAuthority(ServletContext context) {
+        return getSAML2AttributeAuthority(context, getContextParam(context, SAML2_AA_SID_CTX_PARAM,
+                DEFAULT_SAML2_AA_SID));
+    }
+
+    /**
+     * Gets the {@link SAML2AttributeAuthority} bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * @param serviceId the ID under which the service bound
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static SAML2AttributeAuthority getSAML2AttributeAuthority(ServletContext context, String serviceId) {
+        return (SAML2AttributeAuthority) context.getAttribute(serviceId);
+    }
+
+    /**
+     * Gets the {@link SessionManager} service bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static SessionManager<Session> getSessionManager(ServletContext context) {
+        return getSessionManager(context,
+                getContextParam(context, SESSION_MNGR_SID_CTX_PARAM, DEFAULT_SESSION_MNGR_SID));
+    }
+
+    /**
+     * Gets the {@link SessionManager} bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * @param serviceId the ID under which the service bound
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static SessionManager<Session> getSessionManager(ServletContext context, String serviceId) {
+        return (SessionManager<Session>) context.getAttribute(serviceId);
+    }
+
+    /**
+     * Gets the {@link StorageService} service bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static StorageService<?, ?> getStorageService(ServletContext context) {
+        return getStorageService(context, getContextParam(context, STORAGE_SERVICE_SID_CTX_PARAM,
+                DEFAULT_STORAGE_SERVICE_SID));
+    }
+
+    /**
+     * Gets the {@link StorageService} bound to the Servlet context.
+     * 
+     * @param context the Servlet context
+     * @param serviceId the ID under which the service bound
+     * 
+     * @return the service or null if there is no such service bound to the context
+     */
+    public static StorageService<?, ?> getStorageService(ServletContext context, String serviceId) {
+        return (StorageService<?, ?>) context.getAttribute(serviceId);
+    }
+
+    /**
+     * Unbinds a {@link LoginContext} from the current request. The unbinding results in the destruction of the
+     * associated context key cookie and removes the context from the storage service.
+     * 
+     * @param storageService storage service holding the context
+     * @param context the Servlet context
+     * @param httpRequest current HTTP request
+     * @param httpResponse current HTTP response
+     * 
+     * @return the login context that was unbound or null if there was no bound context
+     */
+    public static LoginContext unbindLoginContext(StorageService storageService,
+            ServletContext context, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
+        if (storageService == null || context == null || httpRequest == null || httpResponse == null) {
+            return null;
+        }
+
+        Cookie loginContextKeyCookie = getCookie(httpRequest, LOGIN_CTX_KEY_NAME);
+        if (loginContextKeyCookie == null) {
+            return null;
+        }
+
+        String loginContextKey = DatatypeHelper.safeTrimOrNullString(loginContextKeyCookie.getValue());
+        if (loginContextKey == null) {
+            log.warn("Corrupted LoginContext Key cookie, it did not contain a value");
+        }
+
+        loginContextKeyCookie.setMaxAge(0);
+        httpResponse.addCookie(loginContextKeyCookie);
+
+        LoginContextEntry entry = (LoginContextEntry) storageService.remove(getContextParam(context,
+                LOGIN_CTX_PARTITION_CTX_PARAM, DEFAULT_LOGIN_CTX_PARITION), loginContextKey);
+        if (entry != null && !entry.isExpired()) {
+            return entry.getLoginContext();
+        }
+        return null;
+    }
+
+    // public static Session getUserSession(ServletContext context, HttpServletRequest request) {
+    //
+    // }
+    //
+    // public static Session getUserSession(ServletContext context, String sessionId) {
+    //
+    // }
+}
\ No newline at end of file
index 4acb128..cffdf03 100644 (file)
@@ -1,3 +1,14 @@
+<%@ page import="edu.internet2.middleware.shibboleth.idp.authn.LoginContext" %>
+<%@ page import="edu.internet2.middleware.shibboleth.idp.util.HttpServletHelper" %>
+<%@ page import="org.opensaml.saml2.metadata.*" %>
+
+<%
+   LoginContext loginContext = HttpServletHelper.getLoginContext(HttpServletHelper.getStorageService(application),
+                                                                 application, request);
+   EntityDescriptor entityDescriptor = HttpServletHelper.getRelyingPartyMetadata(loginContext.getRelyingPartyId(),
+                                                   HttpServletHelper.getRelyingPartyConfirmationManager(application));  
+%>
+
 <html>
 
     <head>
@@ -6,7 +17,7 @@
 
        <body>
                <img src="<%= request.getContextPath() %>/images/logo.jpg" />
-               <h2>Shibboleth Identity Provider Login</h2>
+               <h2>Shibboleth Identity Provider Login to <%= entityDescriptor.getEntityID() %></h2>
                
                <% if ("true".equals(request.getAttribute("loginFailed"))) { %>
                <p><font color="red">Authentication Failed</font></p>