[SIDP-384] - Incorrect error message set for expired request in Shibboleth SSO Profile Handler
[SIDP-382] - Less verbose logging for failed attribute queries due to missing name-id
[SIDP-381] - Use duration notation for assertion lifetime in example config files
+[SIDP-380] - Use of forwards between profile handlers and authentication engine causes problems for uApprove
[SIDP-379] - Usage of general AuthenticationException in UsernamePasswordLoginHandler
[SIDP-374] - Switch to use StaticBasicParserPool instead of BasicParserPool
[SIDP-373] - The SLF4J MDC state is not being properly cleared when request processing is done.
import org.joda.time.DateTime;
import org.opensaml.saml2.core.AuthnContext;
+import org.opensaml.util.URLBuilder;
import org.opensaml.util.storage.StorageService;
import org.opensaml.ws.transport.http.HTTPTransportUtils;
import org.opensaml.xml.util.Base64;
forwardRequest("/error.jsp", httpRequest, httpResponse);
} else {
forwardRequest(loginContext.getAuthenticationEngineURL(), httpRequest, httpResponse);
+// URLBuilder urlBuilder = HttpServletHelper.getServletContextUrl(httpRequest);
+// urlBuilder.setPath(urlBuilder.getPath() + loginContext.getAuthenticationEngineURL());
+// String authnEngineUrl = urlBuilder.buildURL();
+// LOG.debug("Redirecting user to authentication engine at {}", authnEngineUrl);
+// try{
+// httpResponse.sendRedirect(authnEngineUrl);
+// }catch(IOException e){
+// LOG.warn("Error sending user back to authentication engine at " + authnEngineUrl, e);
+// }
}
}
forwardRequest("/error.jsp", httpRequest, httpResponse);
}
- // Remove the login context from the replicated store and bind it to the request
- HttpServletHelper.unbindLoginContext(storageService, context, httpRequest, httpResponse);
- HttpServletHelper.bindLoginContext(loginContext, httpRequest);
- LOG.debug("Returning control to profile handler at: {}", loginContext.getProfileHandlerURL());
- forwardRequest(loginContext.getProfileHandlerURL(), httpRequest, httpResponse);
+ URLBuilder urlBuilder = HttpServletHelper.getServletContextUrl(httpRequest);
+ urlBuilder.setPath(urlBuilder.getPath() + loginContext.getProfileHandlerURL());
+ String profileUrl = urlBuilder.buildURL();
+ LOG.debug("Redirecting user to profile handler at {}", profileUrl);
+ try{
+ httpResponse.sendRedirect(profileUrl);
+ }catch(IOException e){
+ LOG.warn("Error sending user back to profile handler at " + profileUrl, e);
+ }
}
/**
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import edu.internet2.middleware.shibboleth.idp.util.HttpServletHelper;
+
/**
* Authenticate a username and password against a JAAS source.
*
public void login(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
// forward control to the servlet.
try {
- StringBuilder pathBuilder = new StringBuilder();
- pathBuilder.append(httpRequest.getContextPath());
+ URLBuilder urlBuilder = HttpServletHelper.getServletContextUrl(httpRequest);
+
+ StringBuilder pathBuilder = new StringBuilder(urlBuilder.getPath());
if (!authenticationServletURL.startsWith("/")) {
pathBuilder.append("/");
}
pathBuilder.append(authenticationServletURL);
-
- URLBuilder urlBuilder = new URLBuilder();
- urlBuilder.setScheme(httpRequest.getScheme());
- urlBuilder.setHost(httpRequest.getServerName());
- urlBuilder.setPort(httpRequest.getServerPort());
urlBuilder.setPath(pathBuilder.toString());
log.debug("Redirecting to {}", urlBuilder.buildURL());
import java.io.IOException;
import java.util.ArrayList;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
+import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.IDPSSODescriptor;
import org.opensaml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.util.URLBuilder;
import org.opensaml.ws.message.decoder.MessageDecodingException;
import org.opensaml.ws.transport.http.HTTPInTransport;
import org.opensaml.ws.transport.http.HTTPOutTransport;
import edu.internet2.middleware.shibboleth.common.relyingparty.provider.SAMLMDRelyingPartyConfigurationManager;
import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml1.ShibbolethSSOConfiguration;
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;
if (DatatypeHelper.isEmpty(authnManagerPath)) {
throw new IllegalArgumentException("Authentication manager path may not be null");
}
- authenticationManagerPath = authnManagerPath;
+ if (authnManagerPath.startsWith("/")) {
+ authenticationManagerPath = authnManagerPath;
+ } else {
+ authenticationManagerPath = "/" + authnManagerPath;
+ }
authnStatementBuilder = (SAMLObjectBuilder<AuthenticationStatement>) getBuilderFactory().getBuilder(
AuthenticationStatement.DEFAULT_ELEMENT_NAME);
log.debug("Processing incoming request");
HttpServletRequest httpRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
- LoginContext loginContext = HttpServletHelper.getLoginContext(httpRequest);
+ HttpServletResponse httpResponse = ((HttpServletResponseAdapter) outTransport).getWrappedResponse();
+ ServletContext servletContext = httpRequest.getSession().getServletContext();
+
+ ShibbolethSSOLoginContext loginContext = (ShibbolethSSOLoginContext) HttpServletHelper.getLoginContext(
+ getStorageService(), servletContext, httpRequest);
if (loginContext == null) {
log.debug("Incoming request does not contain a login context, processing as first leg of request");
performAuthentication(inTransport, outTransport);
} else {
log.debug("Incoming request contains a login context, processing as second leg of request");
- completeAuthenticationRequest(inTransport, outTransport);
+ HttpServletHelper.unbindLoginContext(getStorageService(), servletContext, httpRequest, httpResponse);
+ completeAuthenticationRequest(loginContext, inTransport, outTransport);
}
}
/**
- * Creates a {@link LoginContext} an sends the request off to the AuthenticationManager to begin the process of
- * authenticating the user.
+ * Creates a {@link ShibbolethSSOLoginContext} an sends the request off to the AuthenticationManager to begin the
+ * process of authenticating the user.
*
* @param inTransport inbound message transport
* @param outTransport outbound message transport
throw new ProfileException(msg);
}
- HttpServletHelper.bindLoginContext(loginContext, httpRequest);
+ HttpServletHelper.bindLoginContext(loginContext, getStorageService(), httpRequest.getSession()
+ .getServletContext(), httpRequest, httpResponse);
try {
- RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(authenticationManagerPath);
- dispatcher.forward(httpRequest, httpResponse);
- return;
+ URLBuilder urlBuilder = HttpServletHelper.getServletContextUrl(httpRequest);
+ urlBuilder.setPath(urlBuilder.getPath() + authenticationManagerPath);
+ String authnEngineUrl = urlBuilder.buildURL();
+ log.debug("Redirecting user to authentication engine at {}", authnEngineUrl);
+ httpResponse.sendRedirect(authnEngineUrl);
} catch (IOException e) {
String msg = "Error forwarding Shibboleth SSO request to AuthenticationManager";
log.error(msg, e);
throw new ProfileException(msg, e);
- } catch (ServletException e) {
- String msg = "Error forwarding Shibboleth SSO request to AuthenticationManager";
- log.error(msg, e);
- throw new ProfileException(msg, e);
}
}
protected void decodeRequest(ShibbolethSSORequestContext requestContext, HTTPInTransport inTransport,
HTTPOutTransport outTransport) throws ProfileException {
if (log.isDebugEnabled()) {
- log.debug("Decoding message with decoder binding {}",
- getInboundMessageDecoder(requestContext).getBindingURI());
+ log.debug("Decoding message with decoder binding {}", getInboundMessageDecoder(requestContext)
+ .getBindingURI());
}
HttpServletRequest httpRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
* Creates a response to the Shibboleth SSO and sends the user, with response in tow, back to the relying party
* after they've been authenticated.
*
+ * @param loginContext login context for this request
* @param inTransport inbound message transport
* @param outTransport outbound message transport
*
* @throws ProfileException thrown if the response can not be created and sent back to the relying party
*/
- protected void completeAuthenticationRequest(HTTPInTransport inTransport, HTTPOutTransport outTransport)
- throws ProfileException {
- HttpServletRequest httpRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
- ShibbolethSSOLoginContext loginContext = (ShibbolethSSOLoginContext) HttpServletHelper.getLoginContext(httpRequest);
-
+ protected void completeAuthenticationRequest(ShibbolethSSOLoginContext loginContext, HTTPInTransport inTransport,
+ HTTPOutTransport outTransport) throws ProfileException {
ShibbolethSSORequestContext requestContext = buildRequestContext(loginContext, inTransport, outTransport);
Response samlResponse;
}
resolveAttributes(requestContext);
-
+
ArrayList<Statement> statements = new ArrayList<Statement>();
statements.add(buildAuthenticationStatement(requestContext));
if (requestContext.getProfileConfiguration().includeAttributeStatement()) {
- AttributeStatement attributeStatement = buildAttributeStatement(requestContext,
- "urn:oasis:names:tc:SAML:1.0:cm:bearer");
- if (attributeStatement != null) {
- requestContext.setReleasedAttributes(requestContext.getAttributes().keySet());
- statements.add(attributeStatement);
- }
+ AttributeStatement attributeStatement = buildAttributeStatement(requestContext,
+ "urn:oasis:names:tc:SAML:1.0:cm:bearer");
+ if (attributeStatement != null) {
+ requestContext.setReleasedAttributes(requestContext.getAttributes().keySet());
+ statements.add(attributeStatement);
+ }
}
samlResponse = buildResponse(requestContext, statements);
import java.io.StringReader;
import java.util.ArrayList;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
+import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.opensaml.saml2.metadata.IDPSSODescriptor;
import org.opensaml.saml2.metadata.SPSSODescriptor;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.opensaml.util.URLBuilder;
import org.opensaml.ws.message.decoder.MessageDecodingException;
import org.opensaml.ws.transport.http.HTTPInTransport;
import org.opensaml.ws.transport.http.HTTPOutTransport;
import edu.internet2.middleware.shibboleth.common.relyingparty.provider.SAMLMDRelyingPartyConfigurationManager;
import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml2.SSOConfiguration;
import edu.internet2.middleware.shibboleth.common.util.HttpHelper;
-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;
public SSOProfileHandler(String authnManagerPath) {
super();
- authenticationManagerPath = authnManagerPath;
+ if (DatatypeHelper.isEmpty(authnManagerPath)) {
+ throw new IllegalArgumentException("Authentication manager path may not be null");
+ }
+ if (authnManagerPath.startsWith("/")) {
+ authenticationManagerPath = authnManagerPath;
+ } else {
+ authenticationManagerPath = "/" + authnManagerPath;
+ }
authnStatementBuilder = (SAMLObjectBuilder<AuthnStatement>) getBuilderFactory().getBuilder(
AuthnStatement.DEFAULT_ELEMENT_NAME);
/** {@inheritDoc} */
public void processRequest(HTTPInTransport inTransport, HTTPOutTransport outTransport) throws ProfileException {
HttpServletRequest httpRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
+ HttpServletResponse httpResponse = ((HttpServletResponseAdapter) outTransport).getWrappedResponse();
+ ServletContext servletContext = httpRequest.getSession().getServletContext();
- LoginContext loginContext = HttpServletHelper.getLoginContext(httpRequest);
+ Saml2LoginContext loginContext = (Saml2LoginContext) HttpServletHelper.getLoginContext(getStorageService(),
+ servletContext, httpRequest);
if (loginContext == null) {
log.debug("Incoming request does not contain a login context, processing as first leg of request");
performAuthentication(inTransport, outTransport);
} else {
log.debug("Incoming request contains a login context, processing as second leg of request");
- completeAuthenticationRequest(inTransport, outTransport);
+ HttpServletHelper.unbindLoginContext(getStorageService(), servletContext, httpRequest, httpResponse);
+ completeAuthenticationRequest(loginContext, inTransport, outTransport);
}
}
*/
protected void performAuthentication(HTTPInTransport inTransport, HTTPOutTransport outTransport)
throws ProfileException {
- HttpServletRequest servletRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
+ HttpServletRequest httpRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
+ HttpServletResponse httpResponse = ((HttpServletResponseAdapter) outTransport).getWrappedResponse();
+
SSORequestContext requestContext = new SSORequestContext();
try {
Saml2LoginContext loginContext = new Saml2LoginContext(relyingPartyId, requestContext.getRelayState(),
requestContext.getInboundSAMLMessage());
loginContext.setAuthenticationEngineURL(authenticationManagerPath);
- loginContext.setProfileHandlerURL(HttpHelper.getRequestUriWithoutContext(servletRequest));
+ loginContext.setProfileHandlerURL(HttpHelper.getRequestUriWithoutContext(httpRequest));
loginContext.setDefaultAuthenticationMethod(rpConfig.getDefaultAuthenticationMethod());
- HttpServletHelper.bindLoginContext(loginContext, servletRequest);
- RequestDispatcher dispatcher = servletRequest.getRequestDispatcher(authenticationManagerPath);
- dispatcher.forward(servletRequest, ((HttpServletResponseAdapter) outTransport).getWrappedResponse());
+ HttpServletHelper.bindLoginContext(loginContext, getStorageService(), httpRequest.getSession()
+ .getServletContext(), httpRequest, httpResponse);
+
+ URLBuilder urlBuilder = HttpServletHelper.getServletContextUrl(httpRequest);
+ urlBuilder.setPath(urlBuilder.getPath() + authenticationManagerPath);
+ String authnEngineUrl = urlBuilder.buildURL();
+ log.debug("Redirecting user to authentication engine at {}", authnEngineUrl);
+ httpResponse.sendRedirect(authnEngineUrl);
} catch (MarshallingException e) {
log.error("Unable to marshall authentication request context");
throw new ProfileException("Unable to marshall authentication request context", e);
} catch (IOException ex) {
log.error("Error forwarding SAML 2 AuthnRequest to AuthenticationManager", ex);
throw new ProfileException("Error forwarding SAML 2 AuthnRequest to AuthenticationManager", ex);
- } catch (ServletException ex) {
- log.error("Error forwarding SAML 2 AuthnRequest to AuthenticationManager", ex);
- throw new ProfileException("Error forwarding SAML 2 AuthnRequest to AuthenticationManager", ex);
}
}
* Creates a response to the {@link AuthnRequest} and sends the user, with response in tow, back to the relying
* party after they've been authenticated.
*
+ * @param loginContext login context for this request
* @param inTransport inbound message transport
* @param outTransport outbound message transport
*
* @throws ProfileException thrown if the response can not be created and sent back to the relying party
*/
- protected void completeAuthenticationRequest(HTTPInTransport inTransport, HTTPOutTransport outTransport)
- throws ProfileException {
- HttpServletRequest httpRequest = ((HttpServletRequestAdapter) inTransport).getWrappedRequest();
- Saml2LoginContext loginContext = (Saml2LoginContext) HttpServletHelper.getLoginContext(httpRequest);
-
+ protected void completeAuthenticationRequest(Saml2LoginContext loginContext, HTTPInTransport inTransport,
+ HTTPOutTransport outTransport) throws ProfileException {
SSORequestContext requestContext = buildRequestContext(loginContext, inTransport, outTransport);
Response samlResponse;
try {
checkSamlVersion(requestContext);
checkNameIDPolicy(requestContext);
-
+
if (loginContext.getAuthenticationFailure() != null) {
if (loginContext.getAuthenticationFailure() instanceof PassiveAuthenticationException) {
requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, StatusCode.NO_PASSIVE_URI,
if (nameIdPolcy == null) {
return;
}
-
+
String spNameQualifier = DatatypeHelper.safeTrimOrNullString(nameIdPolcy.getSPNameQualifier());
if (spNameQualifier == null) {
return;
}
-
+
log.debug("Checking if message issuer is a member of affiliation '{}'", spNameQualifier);
try {
EntityDescriptor affiliation = getMetadataProvider().getEntityDescriptor(spNameQualifier);
return subjectLocality;
}
-
+
/** {@inheritDoc} */
protected String getRequiredNameIDFormat(BaseSAMLProfileRequestContext requestContext) {
String requiredNameFormat = null;
AuthnRequest authnRequest = (AuthnRequest) requestContext.getInboundSAMLMessage();
NameIDPolicy nameIdPolicy = authnRequest.getNameIDPolicy();
- if(nameIdPolicy != null){
- requiredNameFormat = DatatypeHelper.safeTrimOrNullString(nameIdPolicy.getFormat());
+ if (nameIdPolicy != null) {
+ requiredNameFormat = DatatypeHelper.safeTrimOrNullString(nameIdPolicy.getFormat());
// Check for unspec'd or encryption formats, which aren't relevant for this section of code.
if (requiredNameFormat != null
&& (NameID.ENCRYPTED.equals(requiredNameFormat) || NameID.UNSPECIFIED.equals(requiredNameFormat))) {
requiredNameFormat = null;
}
}
-
+
return requiredNameFormat;
}
/** {@inheritDoc} */
protected NameID buildNameId(BaseSAML2ProfileRequestContext<?, ?, ?> requestContext) throws ProfileException {
NameID nameId = super.buildNameId(requestContext);
- if(nameId != null){
+ if (nameId != null) {
AuthnRequest authnRequest = (AuthnRequest) requestContext.getInboundSAMLMessage();
NameIDPolicy nameIdPolicy = authnRequest.getNameIDPolicy();
- if(nameIdPolicy != null){
+ if (nameIdPolicy != null) {
String spNameQualifier = DatatypeHelper.safeTrimOrNullString(nameIdPolicy.getSPNameQualifier());
- if(spNameQualifier != null){
+ if (spNameQualifier != null) {
nameId.setSPNameQualifier(spNameQualifier);
- }else{
+ } else {
nameId.setSPNameQualifier(requestContext.getInboundMessageIssuer());
}
}
}
-
+
return nameId;
}
-
+
/**
* Selects the appropriate endpoint for the relying party and stores it in the request context.
*
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.opensaml.util.URLBuilder;
import org.opensaml.util.storage.StorageService;
import org.opensaml.xml.util.DatatypeHelper;
import org.slf4j.Logger;
/** Name of the context initialization parameter that stores the domain to use for all cookies. */
public static final String COOKIE_DOMAIN_PARAM = "cookieDomain";
-
+
/** Name of the cookie containing the IdP session ID: {@value} . */
public static final String IDP_SESSION_COOKIE = "_idp_session";
*
* @param loginContext login context to be bound
* @param httpRequest current HTTP request
+ *
+ * @deprecated
*/
public static void bindLoginContext(LoginContext loginContext, HttpServletRequest httpRequest) {
if (httpRequest == null) {
}
httpRequest.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.
return;
}
- bindLoginContext(loginContext, httpRequest);
-
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);
+ log.debug("Storing LoginContext to StorageService partition {}, key {}", parition, contextKey);
storageService.put(parition, contextKey, entry);
String cookieDomain = getCookieDomain(context);
-
+
Cookie contextKeyCookie = new Cookie(LOGIN_CTX_KEY_NAME, contextKey);
contextKeyCookie.setVersion(1);
- if(cookieDomain != null){
+ if (cookieDomain != null) {
contextKeyCookie.setDomain(cookieDomain);
}
contextKeyCookie.setPath("".equals(httpRequest.getContextPath()) ? "/" : httpRequest.getContextPath());
contextKeyCookie.setSecure(httpRequest.isSecure());
httpResponse.addCookie(contextKeyCookie);
}
-
+
/**
* Gets the domain to use for all cookies.
*
*
* @return domain to use for all cookies
*/
- public static String getCookieDomain(ServletContext context){
+ public static String getCookieDomain(ServletContext context) {
return context.getInitParameter(COOKIE_DOMAIN_PARAM);
}
* @param httpRequest current HTTP request
*
* @return the login context or null if no login context is bound to the request
+ * @deprecated
*/
public static LoginContext getLoginContext(HttpServletRequest httpRequest) {
return (LoginContext) httpRequest.getAttribute(LOGIN_CTX_KEY_NAME);
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;
- }
+ 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();
- }
+ String loginContextKey = DatatypeHelper.safeTrimOrNullString(loginContextKeyCookie.getValue());
+ if (loginContextKey == null) {
+ log.warn("Corrupted LoginContext Key cookie, it did not contain a value");
+ }
+
+ String partition = getContextParam(context, LOGIN_CTX_PARTITION_CTX_PARAM, DEFAULT_LOGIN_CTX_PARITION);
+ log.debug("Looking up LoginContext with key {} from StorageService parition: {}", loginContextKey, partition);
+ LoginContextEntry entry = (LoginContextEntry) storageService.get(partition, loginContextKey);
+ if (entry != null) {
+ if (entry.isExpired()) {
+ log.debug("LoginContext found but it was expired");
} else {
- log.debug("No login context in storage service");
+ log.debug("Retrieved LoginContext with key {} from StorageService parition: {}", loginContextKey,
+ partition);
+ return entry.getLoginContext();
}
+ } else {
+ log.debug("No login context in storage service");
}
- return loginContext;
+ return null;
}
/**
return getRelyingPartyConfigurationManager(context, getContextParam(context, RP_CONFIG_MNGR_SID_CTX_PARAM,
DEFAULT_RP_CONFIG_MNGR_SID));
}
-
+
/**
* Gets the {@link RelyingPartyConfigurationManager} bound to the Servlet context.
*
String serviceId) {
return (RelyingPartyConfigurationManager) context.getAttribute(serviceId);
}
-
+
/**
* Gets the {@link RelyingPartyConfigurationManager} service bound to the Servlet context.
*
* @return the service or null if there is no such service bound to the context
*
* @deprecated use {@link #getRelyingPartyConfigurationManager(ServletContext, String)
+
*/
public static RelyingPartyConfigurationManager getRelyingPartyConfirmationManager(ServletContext context,
String serviceId) {
*/
public static LoginContext unbindLoginContext(StorageService storageService, ServletContext context,
HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
- if (storageService == null || context == null || httpRequest == null || httpResponse == null) {
- return null;
+ log.debug("Unbinding LoginContext");
+ 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");
+ }
+ if (httpResponse == null) {
+ throw new IllegalArgumentException("HTTP request may not be null");
}
Cookie loginContextKeyCookie = getCookie(httpRequest, LOGIN_CTX_KEY_NAME);
if (loginContextKeyCookie == null) {
+ log.debug("No LoginContext cookie available, no unbinding necessary.");
return null;
}
String loginContextKey = DatatypeHelper.safeTrimOrNullString(loginContextKeyCookie.getValue());
if (loginContextKey == null) {
log.warn("Corrupted LoginContext Key cookie, it did not contain a value");
+ return null;
}
- httpRequest.setAttribute(LOGIN_CTX_KEY_NAME, null);
+ log.debug("Expiring LoginContext cookie");
loginContextKeyCookie.setMaxAge(0);
loginContextKeyCookie.setPath("".equals(httpRequest.getContextPath()) ? "/" : httpRequest.getContextPath());
loginContextKeyCookie.setVersion(1);
httpResponse.addCookie(loginContextKeyCookie);
- LoginContextEntry entry = (LoginContextEntry) storageService.remove(getContextParam(context,
- LOGIN_CTX_PARTITION_CTX_PARAM, DEFAULT_LOGIN_CTX_PARITION), loginContextKey);
+ String storageServicePartition = getContextParam(context, LOGIN_CTX_PARTITION_CTX_PARAM,
+ DEFAULT_LOGIN_CTX_PARITION);
+
+ log.debug("Removing LoginContext, with key {}, from StorageService partition {}", loginContextKey,
+ storageServicePartition);
+ LoginContextEntry entry = (LoginContextEntry) storageService.remove(storageServicePartition, loginContextKey);
if (entry != null && !entry.isExpired()) {
return entry.getLoginContext();
}
+
return null;
}
+
+ /**
+ * Builds a URL, up to and including the servlet context path. URL does not include a trailing "/".
+ *
+ * @param httpRequest httpRequest made to the servlet in question
+ *
+ * @return URL builder containing the scheme, server name, server port, and context path
+ */
+ public static URLBuilder getServletContextUrl(HttpServletRequest httpRequest) {
+ URLBuilder urlBuilder = new URLBuilder();
+ urlBuilder.setScheme(httpRequest.getScheme());
+ urlBuilder.setHost(httpRequest.getServerName());
+ urlBuilder.setPort(httpRequest.getServerPort());
+ urlBuilder.setPath(httpRequest.getContextPath());
+ return urlBuilder;
+ }
}
\ No newline at end of file
import java.security.Principal;
import javax.security.auth.Subject;
+import javax.servlet.http.HttpServletRequest;
import org.joda.time.DateTime;
import org.opensaml.common.SAMLObjectBuilder;
import org.opensaml.xml.util.XMLHelper;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
import org.w3c.dom.Element;
import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
import edu.internet2.middleware.shibboleth.common.profile.ProfileHandler;
import edu.internet2.middleware.shibboleth.common.profile.ProfileHandlerManager;
+import edu.internet2.middleware.shibboleth.common.profile.provider.AbstractShibbolethProfileHandler;
+import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
import edu.internet2.middleware.shibboleth.idp.authn.Saml2LoginContext;
import edu.internet2.middleware.shibboleth.idp.authn.UsernamePrincipal;
import edu.internet2.middleware.shibboleth.idp.session.AuthenticationMethodInformation;
/** Tests initial leg of the SSO request where request is decoded and sent to the authentication engine. */
public void testFirstAuthenticationLeg() throws Exception {
+ MockServletContext servletContext = new MockServletContext();
+
MockHttpServletRequest servletRequest = buildServletRequest("urn:example.org:sp1");
MockHttpServletResponse servletResponse = new MockHttpServletResponse();
ProfileHandlerManager handlerManager = (ProfileHandlerManager) getApplicationContext().getBean(
"shibboleth.HandlerManager");
- ProfileHandler handler = handlerManager.getProfileHandler(servletRequest);
+ AbstractShibbolethProfileHandler handler = (AbstractShibbolethProfileHandler) handlerManager.getProfileHandler(servletRequest);
assertNotNull(handler);
// Process request
HTTPOutTransport profileResponse = new HttpServletResponseAdapter(servletResponse, false);
handler.processRequest(profileRequest, profileResponse);
- Saml2LoginContext loginContext = (Saml2LoginContext) HttpServletHelper.getLoginContext(servletRequest);
+ servletRequest.setCookies(servletResponse.getCookies());
+ Saml2LoginContext loginContext = (Saml2LoginContext) HttpServletHelper.getLoginContext(handler.getStorageService(), servletContext, servletRequest);
assertNotNull(loginContext);
assertEquals(false, loginContext.getAuthenticationAttempted());
assertEquals("urn:example.org:sp1", loginContext.getRelyingPartyId());
assertEquals(0, loginContext.getRequestedAuthenticationMethods().size());
- assertEquals("/AuthnEngine", servletResponse.getForwardedUrl());
+ assertTrue(servletResponse.getRedirectedUrl().endsWith("/AuthnEngine"));
}
/** Tests second leg of the SSO request where request returns to SSO handler and AuthN statement is generated. */
public void testSecondAuthenticationLeg() throws Exception {
+ MockServletContext servletContext = new MockServletContext();
MockHttpServletRequest servletRequest = buildServletRequest("urn:example.org:sp1");
MockHttpServletResponse servletResponse = new MockHttpServletResponse();
- HttpServletHelper.bindLoginContext(buildLoginContext("urn:example.org:sp1"), servletRequest);
-
ProfileHandlerManager handlerManager = (ProfileHandlerManager) getApplicationContext().getBean(
"shibboleth.HandlerManager");
- ProfileHandler handler = handlerManager.getProfileHandler(servletRequest);
+ AbstractShibbolethProfileHandler handler = (AbstractShibbolethProfileHandler) handlerManager.getProfileHandler(servletRequest);
assertNotNull(handler);
+
+ HttpServletHelper.bindLoginContext(buildLoginContext("urn:example.org:sp1"), handler.getStorageService(), servletContext,
+ servletRequest, servletResponse);
+ servletRequest.setCookies(servletResponse.getCookies());
// Process request
HTTPInTransport profileRequest = new HttpServletRequestAdapter(servletRequest);
import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
import edu.internet2.middleware.shibboleth.common.profile.ProfileHandler;
import edu.internet2.middleware.shibboleth.common.profile.ProfileHandlerManager;
+import edu.internet2.middleware.shibboleth.common.profile.provider.AbstractShibbolethProfileHandler;
import edu.internet2.middleware.shibboleth.idp.authn.ShibbolethSSOLoginContext;
import edu.internet2.middleware.shibboleth.idp.authn.UsernamePrincipal;
import edu.internet2.middleware.shibboleth.idp.session.AuthenticationMethodInformation;
/** Tests initial leg of the SSO request where request is decoded and sent to the authentication engine. */
public void testFirstAuthenticationLeg() throws Exception {
+ MockServletContext servletContext = new MockServletContext();
+
MockHttpServletRequest servletRequest = buildServletRequest();
MockHttpServletResponse servletResponse = new MockHttpServletResponse();
ProfileHandlerManager handlerManager = (ProfileHandlerManager) getApplicationContext().getBean(
"shibboleth.HandlerManager");
- ProfileHandler handler = handlerManager.getProfileHandler(servletRequest);
+ AbstractShibbolethProfileHandler handler = (AbstractShibbolethProfileHandler) handlerManager
+ .getProfileHandler(servletRequest);
assertNotNull(handler);
// Process request
HTTPOutTransport profileResponse = new HttpServletResponseAdapter(servletResponse, false);
handler.processRequest(profileRequest, profileResponse);
- ShibbolethSSOLoginContext loginContext = (ShibbolethSSOLoginContext) HttpServletHelper
- .getLoginContext(servletRequest);
+ servletRequest.setCookies(servletResponse.getCookies());
+ ShibbolethSSOLoginContext loginContext = (ShibbolethSSOLoginContext) HttpServletHelper.getLoginContext(handler
+ .getStorageService(), servletContext, servletRequest);
assertNotNull(loginContext);
assertEquals(false, loginContext.getAuthenticationAttempted());
assertEquals("urn:example.org:sp1", loginContext.getRelyingPartyId());
assertEquals(0, loginContext.getRequestedAuthenticationMethods().size());
assertEquals("https://example.org/mySP", loginContext.getSpAssertionConsumerService());
- assertEquals("https://example.org/mySP", loginContext.getSpTarget());
+ assertEquals("https://example.org/mySP", loginContext.getSpAssertionConsumerService());
- assertEquals("/AuthnEngine", servletResponse.getForwardedUrl());
+ assertTrue(servletResponse.getRedirectedUrl().endsWith("/AuthnEngine"));
}
/** Tests second leg of the SSO request where request returns to SSO handler and AuthN statement is generated. */
public void testSecondAuthenticationLeg() throws Exception {
+ MockServletContext servletContext = new MockServletContext();
MockHttpServletRequest servletRequest = buildServletRequest();
MockHttpServletResponse servletResponse = new MockHttpServletResponse();
- HttpServletHelper.bindLoginContext(buildLoginContext(), servletRequest);
-
ProfileHandlerManager handlerManager = (ProfileHandlerManager) getApplicationContext().getBean(
"shibboleth.HandlerManager");
- ProfileHandler handler = handlerManager.getProfileHandler(servletRequest);
+ AbstractShibbolethProfileHandler handler = (AbstractShibbolethProfileHandler) handlerManager
+ .getProfileHandler(servletRequest);
assertNotNull(handler);
+ HttpServletHelper.bindLoginContext(buildLoginContext(), handler.getStorageService(), servletContext,
+ servletRequest, servletResponse);
+ servletRequest.setCookies(servletResponse.getCookies());
+
// Process request
HTTPInTransport profileRequest = new HttpServletRequestAdapter(servletRequest);
HTTPOutTransport profileResponse = new HttpServletResponseAdapter(servletResponse, false);