/** the key in a HttpSession where login contexts are stored. */
public static final String LOGIN_CONTEXT_KEY = "shib2.logincontext";
-
+
/** Serial version UID. */
private static final long serialVersionUID = 4268661186941572372L;
/**
* Sets if authentication must be forced.
*
- * @param forceAuth if the authentication manager must reauth the user.
+ * @param force if the authentication manager must reauth the user.
*/
- public void setForceAuth(boolean forceAuth) {
- this.forceAuth = forceAuth;
+ public void setForceAuth(boolean force) {
+ forceAuth = force;
}
/**
* Sets if authentication must be passive.
*
- * @param passiveAuth if the authentication manager must not interact with the users UI.
+ * @param passicve if the authentication manager must not interact with the users UI.
*/
- public void setPassiveAuth(boolean passiveAuth) {
- this.passiveAuth = passiveAuth;
+ public void setPassiveAuth(boolean passicve) {
+ passiveAuth = passicve;
}
/**
/**
* Sets the ProfileHandler URL.
*
- * @param profileHandlerURL The URL of the profile handler that invoked the AuthenticationManager/
+ * @param url The URL of the profile handler that invoked the AuthenticationManager/
*/
- public void setProfileHandlerURL(String profileHandlerURL) {
- this.profileHandlerURL = profileHandlerURL;
+ public void setProfileHandlerURL(String url) {
+ profileHandlerURL = url;
}
/**
/**
* Sets the AuthenticationManager's URL.
*
- * @param authnManagerURL the URL of the AuthenticationManager.
+ * @param url the URL of the AuthenticationManager.
*/
- public void setAuthenticationManagerURL(String authnManagerURL) {
- this.authnManagerURL = authnManagerURL;
+ public void setAuthenticationManagerURL(String url) {
+ authnManagerURL = url;
}
/**
/**
* Sets the authentication instant.
*
- * @param authnInstant The instant of authentication.
+ * @param instant The instant of authentication.
*/
- public void setAuthenticationInstant(final DateTime authnInstant) {
- this.authnInstant = authnInstant;
+ public void setAuthenticationInstant(final DateTime instant) {
+ authnInstant = instant;
}
/**
/**
* Sets the duration of authentication.
*
- * @param authnDuration The duration of authentication.
+ * @param duration The duration of authentication.
*/
- public void setAuthenticationDuration(long authnDuration) {
- this.authnDuration = authnDuration;
+ public void setAuthenticationDuration(long duration) {
+ authnDuration = duration;
}
/**
/**
* Sets the method used to authenticate the user.
*
- * @param authnMethod The method used to authenticate the user.
+ * @param method The method used to authenticate the user.
*/
- public void setAuthenticationMethod(String authnMethod) {
- this.authnMethod = authnMethod;
+ public void setAuthenticationMethod(String method) {
+ authnMethod = method;
}
/**
- * Gets the {@link Session} ID
+ * Gets the {@link Session} ID.
*
- * @return the Session id.
+ * @return the Session id
*/
public String getSessionID() {
return sessionID;
}
/**
- * Sets the {@link Session} ID
+ * Sets the {@link Session} ID.
*
- * @param sessionID the Session ID
+ * @param id the Session ID
*/
- public void setSessionID(String sessionID) {
- this.sessionID = sessionID;
+ public void setSessionID(String id) {
+ sessionID = id;
}
/**
public List<String> getRequestedAuthenticationMethods() {
return new ArrayList<String>();
}
-}
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright [2007] [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.authn;
+
+/** Shibboleth SSO aware extension to {@link LoginContext}. */
+public class ShibbolethSSOLoginContext extends LoginContext {
+
+ /** Serial version UID. */
+ private static final long serialVersionUID = -8388394528549536613L;
+
+ /** Service provider assertion consumer service URL. */
+ private String spAssertionConsumerService;
+
+ /** Service provider target URL. */
+ private String spTarget;
+
+ /** Constructor. */
+ public ShibbolethSSOLoginContext() {
+ super(false, false);
+ }
+
+ /**
+ * Gets the service provider assertion consumer service URL.
+ *
+ * @return service provider assertion consumer service URL
+ */
+ public String getSpAssertionConsumerService() {
+ return spAssertionConsumerService;
+ }
+
+ /**
+ * Sets the service provider assertion consumer service URL.
+ *
+ * @param url service provider assertion consumer service URL
+ */
+ public void setSpAssertionConsumerService(String url) {
+ spAssertionConsumerService = url;
+ }
+
+ /**
+ * Gets the service provider target URL.
+ *
+ * @return service provider target URL
+ */
+ public String getSpTarget() {
+ return spTarget;
+ }
+
+ /**
+ * Sets the service provider target URL.
+ *
+ * @param url service provider target URL
+ */
+ public void setSpTarget(String url) {
+ spTarget = url;
+ }
+}
\ No newline at end of file
import org.opensaml.common.SAMLVersion;
import org.opensaml.common.impl.SAMLObjectContentReference;
import org.opensaml.common.xml.SAMLConstants;
+import org.opensaml.log.Level;
import org.opensaml.saml1.core.Assertion;
+import org.opensaml.saml1.core.AttributeQuery;
+import org.opensaml.saml1.core.AttributeStatement;
import org.opensaml.saml1.core.Audience;
import org.opensaml.saml1.core.AudienceRestrictionCondition;
import org.opensaml.saml1.core.Conditions;
import edu.internet2.middleware.shibboleth.common.attribute.BaseAttribute;
import edu.internet2.middleware.shibboleth.common.attribute.encoding.AttributeEncoder;
import edu.internet2.middleware.shibboleth.common.attribute.encoding.AttributeEncodingException;
+import edu.internet2.middleware.shibboleth.common.attribute.provider.SAML1AttributeAuthority;
+import edu.internet2.middleware.shibboleth.common.attribute.provider.ShibbolethSAMLAttributeRequestContext;
+import edu.internet2.middleware.shibboleth.common.log.AuditLogEntry;
import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
import edu.internet2.middleware.shibboleth.common.profile.ProfileRequest;
import edu.internet2.middleware.shibboleth.common.profile.ProfileResponse;
import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml1.AbstractSAML1ProfileConfiguration;
import edu.internet2.middleware.shibboleth.idp.profile.AbstractSAMLProfileHandler;
+import edu.internet2.middleware.shibboleth.idp.session.ServiceInformation;
+import edu.internet2.middleware.shibboleth.idp.session.Session;
-/**
- * Common implementation details for profile handlers.
- */
+/** Common implementation details for profile handlers. */
public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHandler {
/** SAML Version for this profile handler. */
* @return the built response
*
* @throws ProfileException thrown if there is a problem creating the SAML response
- * @throws AttributeRequestException thrown if there is a problem resolving attributes
*/
protected Response buildResponse(SAML1ProfileRequestContext requestContext, List<Statement> statements)
- throws ProfileException, AttributeRequestException {
+ throws ProfileException {
DateTime issueInstant = new DateTime();
}
}
} catch (AttributeEncodingException e) {
+ requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null,
+ "Unable to construct NameIdentifier"));
throw new ProfileException("Unable to encode NameIdentifier attribute", e);
}
}
+ requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "Unable to construct NameID"));
throw new ProfileException("No principal attributes support NameIdentifier construction");
}
return nameFormats;
} catch (MetadataProviderException e) {
+ requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "Unable to lookup metadata"));
throw new ProfileException("Unable to determine lookup entity metadata", e);
}
}
/**
* Constructs an SAML response message carrying a request error.
*
- * @param requestContext current request context
- * @param topLevelCode top-level status code
- * @param secondLevelCode second-level status code
- * @param failureMessage An optional second-level failure message
+ * @param requestContext current request context containing the failure status
*
* @return the constructed error response
*/
- protected Response buildErrorResponse(SAML1ProfileRequestContext requestContext, String topLevelCode,
- String secondLevelCode, String failureMessage) {
+ protected Response buildErrorResponse(SAML1ProfileRequestContext requestContext) {
Response samlResponse = getResponseBuilder().buildObject();
samlResponse.setIssueInstant(new DateTime());
populateStatusResponse(requestContext, samlResponse);
- Status status = buildStatus(topLevelCode, secondLevelCode, failureMessage);
- samlResponse.setStatus(status);
+ samlResponse.setStatus(requestContext.getFailureStatus());
return samlResponse;
}
}
/**
+ * Executes a query for attributes and builds a SAML attribute statement from the results.
+ *
+ * @param requestContext current request context
+ * @param subjectConfMethod subject confirmation method
+ *
+ * @return attribute statement resulting from the query
+ *
+ * @throws ProfileException thrown if there is a problem making the query
+ */
+ protected AttributeStatement buildAttributeStatement(SAML1ProfileRequestContext requestContext, String subjectConfMethod)
+ throws ProfileException {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Creating attribute statement in response to SAML request from relying party "
+ + requestContext.getRelyingPartyId());
+ }
+
+ AbstractSAML1ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
+ SAML1AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
+
+ try {
+ if (log.isDebugEnabled()) {
+ log.debug("Resolving attributes for principal " + requestContext.getPrincipalName()
+ + " of SAML request from relying party " + requestContext.getRelyingPartyId());
+ }
+ Map<String, BaseAttribute> principalAttributes = attributeAuthority
+ .getAttributes(buildAttributeRequestContext(requestContext));
+
+ requestContext.setPrincipalAttributes(principalAttributes);
+
+ AttributeStatement statment;
+ if (requestContext.getSamlRequest() instanceof AttributeQuery) {
+ statment = attributeAuthority.buildAttributeStatement((AttributeQuery) requestContext.getSamlRequest(),
+ principalAttributes.values());
+ } else {
+ statment = attributeAuthority.buildAttributeStatement(null, principalAttributes.values());
+ }
+
+ Subject statementSubject = buildSubject(requestContext, subjectConfMethod);
+ statment.setSubject(statementSubject);
+
+ return statment;
+ } catch (AttributeRequestException e) {
+ log.error("Error resolving attributes for SAML request from relying party "
+ + requestContext.getRelyingPartyId(), e);
+ requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "Error resolving attributes"));
+ throw new ProfileException("Error resolving attributes for SAML request from relying party "
+ + requestContext.getRelyingPartyId(), e);
+ }
+ }
+
+ /**
+ * Resolves the principal name of the subject of the request.
+ *
+ * @param requestContext current request context
+ *
+ * @throws ProfileException thrown if the principal name can not be resolved
+ */
+ protected void resolvePrincipal(SAML1ProfileRequestContext requestContext) throws ProfileException {
+ AbstractSAML1ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
+ SAML1AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Resolving principal name for subject of SAML request from relying party "
+ + requestContext.getRelyingPartyId());
+ }
+
+ try {
+ String principal = attributeAuthority.getPrincipal(buildAttributeRequestContext(requestContext));
+ requestContext.setPrincipalName(principal);
+ } catch (AttributeRequestException e) {
+ log.error("Error resolving attributes for SAML request from relying party "
+ + requestContext.getRelyingPartyId(), e);
+ requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, StatusCode.REQUEST_DENIED,
+ "Error resolving principal"));
+ throw new ProfileException("Error resolving attributes for SAML request from relying party "
+ + requestContext.getRelyingPartyId(), e);
+ }
+ }
+
+ /**
+ * Creates an attribute query context from the current profile request context.
+ *
+ * @param requestContext current profile request
+ *
+ * @return created query context
+ */
+ protected ShibbolethSAMLAttributeRequestContext<NameIdentifier, AttributeQuery> buildAttributeRequestContext(
+ SAML1ProfileRequestContext requestContext) {
+
+ ShibbolethSAMLAttributeRequestContext<NameIdentifier, AttributeQuery> queryContext;
+
+ if (requestContext.getSamlRequest() instanceof AttributeQuery) {
+ queryContext = new ShibbolethSAMLAttributeRequestContext<NameIdentifier, AttributeQuery>(
+ getMetadataProvider(), requestContext.getRelyingPartyConfiguration(),
+ (AttributeQuery) requestContext.getSamlRequest());
+ } else {
+ queryContext = new ShibbolethSAMLAttributeRequestContext<NameIdentifier, AttributeQuery>(
+ getMetadataProvider(), requestContext.getRelyingPartyConfiguration());
+ }
+
+ queryContext.setAttributeRequester(requestContext.getAssertingPartyId());
+ queryContext.setPrincipalName(requestContext.getPrincipalName());
+ queryContext.setProfileConfiguration(requestContext.getProfileConfiguration());
+ queryContext.setRequest(requestContext.getProfileRequest());
+
+ Session userSession = getSessionManager().getSession(getUserSessionId(requestContext.getProfileRequest()));
+ if (userSession != null) {
+ queryContext.setUserSession(userSession);
+ ServiceInformation serviceInfo = userSession.getServiceInformation(requestContext.getRelyingPartyId());
+ if (serviceInfo != null) {
+ String principalAuthenticationMethod = serviceInfo.getAuthenticationMethod().getAuthenticationMethod();
+
+ requestContext.setPrincipalAuthenticationMethod(principalAuthenticationMethod);
+ queryContext.setPrincipalAuthenticationMethod(principalAuthenticationMethod);
+ }
+ }
+
+ return queryContext;
+ }
+
+ /**
* Signs the given assertion if either the current profile configuration or the relying party configuration contains
* signing credentials.
*
}
/**
+ * Writes an aduit log entry indicating the successful response to the attribute request.
+ *
+ * @param context current request context
+ */
+ protected void writeAuditLogEntry(SAML1ProfileRequestContext context) {
+ AuditLogEntry auditLogEntry = new AuditLogEntry();
+ auditLogEntry.setMessageProfile(getProfileId());
+ auditLogEntry.setPrincipalAuthenticationMethod(context.getPrincipalAuthenticationMethod());
+ auditLogEntry.setPrincipalName(context.getPrincipalName());
+ auditLogEntry.setAssertingPartyId(context.getAssertingPartyId());
+ auditLogEntry.setRelyingPartyId(context.getRelyingPartyId());
+ auditLogEntry.setRequestBinding(context.getMessageDecoder().getBindingURI());
+ auditLogEntry.setRequestId(null);
+ auditLogEntry.setResponseBinding(context.getMessageEncoder().getBindingURI());
+ auditLogEntry.setResponseId(context.getSamlResponse().getID());
+ getAduitLog().log(Level.CRITICAL, auditLogEntry);
+ }
+
+ /**
* Contextual object used to accumlate information as profile requests are being processed.
*
* @param <RequestType> type of SAML 1 request
/** The NameIdentifier of the subject of this request. */
private NameIdentifier subjectNameIdentifier;
+ /** The request failure status. */
+ private Status failureStatus;
+
/**
* Constructor.
*
public void setSamlResponse(ResponseType response) {
samlResponse = response;
}
+
+ /**
+ * Gets the status reflecting a request failure.
+ *
+ * @return status reflecting a request failure
+ */
+ public Status getFailureStatus() {
+ return failureStatus;
+ }
+
+ /**
+ * Sets the status reflecting a request failure.
+ *
+ * @param status status reflecting a request failure
+ */
+ public void setFailureStatus(Status status) {
+ failureStatus = status;
+ }
}
}
\ No newline at end of file
package edu.internet2.middleware.shibboleth.idp.profile.saml1;
import java.util.ArrayList;
-import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.opensaml.saml1.binding.decoding.HTTPSOAP11Decoder;
import org.opensaml.saml1.binding.encoding.HTTPSOAP11Encoder;
import org.opensaml.saml1.core.AttributeQuery;
-import org.opensaml.saml1.core.AttributeStatement;
-import org.opensaml.saml1.core.NameIdentifier;
import org.opensaml.saml1.core.Response;
import org.opensaml.saml1.core.Statement;
import org.opensaml.saml1.core.StatusCode;
-import org.opensaml.saml1.core.Subject;
import org.opensaml.saml2.metadata.AttributeAuthorityDescriptor;
import org.opensaml.saml2.metadata.SPSSODescriptor;
import org.opensaml.ws.security.SecurityPolicyException;
-import edu.internet2.middleware.shibboleth.common.attribute.AttributeRequestException;
-import edu.internet2.middleware.shibboleth.common.attribute.BaseAttribute;
-import edu.internet2.middleware.shibboleth.common.attribute.provider.SAML1AttributeAuthority;
-import edu.internet2.middleware.shibboleth.common.attribute.provider.ShibbolethSAMLAttributeRequestContext;
import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
import edu.internet2.middleware.shibboleth.common.profile.ProfileRequest;
import edu.internet2.middleware.shibboleth.common.profile.ProfileResponse;
import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfiguration;
import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml1.AttributeQueryConfiguration;
-import edu.internet2.middleware.shibboleth.idp.session.ServiceInformation;
-import edu.internet2.middleware.shibboleth.idp.session.Session;
/**
* SAML 1 Attribute Query profile handler.
try {
decodeRequest(requestContext);
+ resolvePrincipal(requestContext);
+
ArrayList<Statement> statements = new ArrayList<Statement>();
- statements.add(buildAttributeStatement(requestContext));
+ statements.add(buildAttributeStatement(requestContext, "urn:oasis:names:tc:SAML:1.0:cm:sender-vouches"));
samlResponse = buildResponse(requestContext, statements);
- } catch (SecurityPolicyException e) {
- samlResponse = buildErrorResponse(requestContext, StatusCode.REQUESTER, StatusCode.REQUEST_DENIED, e
- .getMessage());
- } catch (AttributeRequestException e) {
- samlResponse = buildErrorResponse(requestContext, StatusCode.RESPONDER, null, e.getMessage());
} catch (ProfileException e) {
- samlResponse = buildErrorResponse(requestContext, StatusCode.RESPONDER, StatusCode.REQUEST_DENIED, e
- .getMessage());
+ samlResponse = buildErrorResponse(requestContext);
}
}
* @param requestContext request context contianing the request to decode
*
* @throws ProfileException throw if there is a problem decoding the request
- * @throws SecurityPolicyException thrown if the message was decoded properly but did not meet the necessary
- * security policy requirements
*/
- protected void decodeRequest(AttributeQueryContext requestContext) throws ProfileException, SecurityPolicyException {
+ protected void decodeRequest(AttributeQueryContext requestContext) throws ProfileException {
if (log.isDebugEnabled()) {
log.debug("Decoding incomming request");
}
}
} catch (BindingException e) {
log.error("Error decoding attribute query message", e);
+ requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "Error decoding message"));
throw new ProfileException("Error decoding attribute query message");
+ } catch (SecurityPolicyException e) {
+ log.error("Message did not meet security policy requirements", e);
+ requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, StatusCode.REQUEST_DENIED,
+ "Message did not meet security policy requirements"));
+ throw new ProfileException("Message did not meet security policy requirements", e);
} finally {
// Set as much information as can be retrieved from the decoded message
SAMLSecurityPolicy securityPolicy = requestContext.getMessageDecoder().getSecurityPolicy();
}
/**
- * Executes a query for attributes and builds a SAML attribute statement from the results.
- *
- * @param requestContext current request context
- *
- * @return attribute statement resulting from the query
- *
- * @throws ProfileException thrown if there is a problem making the query
- * @throws AttributeRequestException thrown if there is a problem resolving attributes
- */
- protected AttributeStatement buildAttributeStatement(AttributeQueryContext requestContext) throws ProfileException,
- AttributeRequestException {
-
- if (log.isDebugEnabled()) {
- log.debug("Creating attribute statement in response to SAML request from relying party "
- + requestContext.getRelyingPartyId());
- }
-
- try {
- AttributeQueryConfiguration profileConfiguration = requestContext.getProfileConfiguration();
- if (profileConfiguration == null) {
- log.error("No SAML 1 attribute query profile configuration is defined for relying party: "
- + requestContext.getRelyingPartyId());
- throw new AttributeRequestException("SAML 1 attribute query is not configured for this relying party");
- }
-
- SAML1AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
-
- ShibbolethSAMLAttributeRequestContext<NameIdentifier, AttributeQuery> attributeRequestContext = buildAttributeRequestContext(requestContext);
-
- if (log.isDebugEnabled()) {
- log.debug("Resolving principal name for subject of SAML request from relying party "
- + requestContext.getRelyingPartyId());
- }
- String principal = attributeAuthority.getPrincipal(attributeRequestContext);
- requestContext.setPrincipalName(principal);
-
- if (log.isDebugEnabled()) {
- log.debug("Resolving attributes for principal " + principal + " of SAML request from relying party "
- + requestContext.getRelyingPartyId());
- }
- Map<String, BaseAttribute> principalAttributes = attributeAuthority
- .getAttributes(buildAttributeRequestContext(requestContext));
-
- requestContext.setPrincipalAttributes(principalAttributes);
-
- AttributeStatement statment = attributeAuthority.buildAttributeStatement(requestContext.getSamlRequest(),
- principalAttributes.values());
-
- Subject statementSubject = buildSubject(requestContext, "urn:oasis:names:tc:SAML:1.0:cm:sender-vouches");
- statment.setSubject(statementSubject);
-
- return statment;
- } catch (AttributeRequestException e) {
- log.error("Error resolving attributes for SAML request from relying party "
- + requestContext.getRelyingPartyId(), e);
- throw e;
- }
- }
-
- /**
- * Creates an attribute query context from the current profile request context.
- *
- * @param requestContext current profile request
- *
- * @return created query context
- */
- protected ShibbolethSAMLAttributeRequestContext<NameIdentifier, AttributeQuery> buildAttributeRequestContext(
- AttributeQueryContext requestContext) {
-
- ShibbolethSAMLAttributeRequestContext<NameIdentifier, AttributeQuery> queryContext = new ShibbolethSAMLAttributeRequestContext<NameIdentifier, AttributeQuery>(
- getMetadataProvider(), requestContext.getRelyingPartyConfiguration(), requestContext.getSamlRequest());
-
- queryContext.setAttributeRequester(requestContext.getAssertingPartyId());
- queryContext.setPrincipalName(requestContext.getPrincipalName());
- queryContext.setProfileConfiguration(requestContext.getProfileConfiguration());
- queryContext.setRequest(requestContext.getProfileRequest());
-
- Session userSession = getSessionManager().getSession(getUserSessionId(requestContext.getProfileRequest()));
- if (userSession != null) {
- queryContext.setUserSession(userSession);
- ServiceInformation serviceInfo = userSession.getServiceInformation(requestContext.getRelyingPartyId());
- if (serviceInfo != null) {
- String principalAuthenticationMethod = serviceInfo.getAuthenticationMethod().getAuthenticationMethod();
-
- requestContext.setPrincipalAuthenticationMethod(principalAuthenticationMethod);
- queryContext.setPrincipalAuthenticationMethod(principalAuthenticationMethod);
- }
- }
-
- return queryContext;
- }
-
- /**
* Encodes the request's SAML response and writes it to the servlet response.
*
* @param requestContext current request context
+++ /dev/null
-/*
- * Copyright [2006] [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.profile.saml1;
-
-import java.io.UnsupportedEncodingException;
-import java.io.IOException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.servlet.RequestDispatcher;
-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 javax.servlet.http.HttpSession;
-
-import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
-import edu.internet2.middleware.shibboleth.common.profile.ProfileRequest;
-import edu.internet2.middleware.shibboleth.common.profile.ProfileResponse;
-import edu.internet2.middleware.shibboleth.common.relyingparty.ProfileConfiguration;
-import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfiguration;
-import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml1.ShibbolethSSOConfiguration;
-import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
-
-
-import org.apache.log4j.Logger;
-import org.bouncycastle.util.encoders.Hex;
-import org.joda.time.DateTime;
-import org.opensaml.common.SAMLObjectBuilder;
-import org.opensaml.saml1.core.Assertion;
-import org.opensaml.saml1.core.Audience;
-import org.opensaml.saml1.core.AudienceRestrictionCondition;
-import org.opensaml.saml1.core.AuthenticationStatement;
-import org.opensaml.saml1.core.Conditions;
-import org.opensaml.saml1.core.ConfirmationMethod;
-import org.opensaml.saml1.core.NameIdentifier;
-import org.opensaml.saml1.core.Response;
-import org.opensaml.saml1.core.Status;
-import org.opensaml.saml1.core.Subject;
-import org.opensaml.saml1.core.SubjectConfirmation;
-import org.opensaml.saml2.metadata.AssertionConsumerService;
-import org.opensaml.saml2.metadata.Endpoint;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
-
-/**
- * Shibboleth, version 1.X, single sign-on profile handler.
- *
- * This profile implements the SSO profile from "Shibboleth Architecture Protocols and Profiles" - 10 September 2005.
- */
-public class ShibbolethSSO extends AbstractSAML1ProfileHandler {
-
-
- /**
- * Request context for a ShibbolethSSO request.
- */
- protected class ShibbolethSSORequestContext {
-
- /** The servlet request. */
- protected HttpServletRequest servletRequest;
-
- /** The servlet response. */
- protected HttpServletResponse servletResponse;
-
- /** The profile request. */
- protected ProfileRequest<ServletRequest> profileRequest;
-
- /** The profile response. */
- protected ProfileResponse<ServletResponse> profileResponse;
-
- /** The AssertionConsumerService ("shire") URL. */
- protected String shire;
-
- /** The location to which the response should be sent ("target"). */
- protected String target;
-
- /** The SP's providerId in the metadata. */
- protected String providerId;
-
- /** The requestor's address. */
- protected String remoteAddr;
-
- /** The Shibboleth {@link LoginContext}. */
- protected LoginContext loginContex;
-
- /** The RelyingPartyConfiguration for the request. */
- protected RelyingPartyConfiguration rpConfiguration;
-
- /** The ShibbolethSSOConfiguration. */
- protected ShibbolethSSOConfiguration shibSSOConfiguration;
-
- /** The SPSSODescriptor. */
- protected SPSSODescriptor spDescriptor;
-
- /** The AssertionConsumerService to which the assertion should be sent. */
- protected AssertionConsumerService assertionConsumerService;
-
- /** The Assertion we generate in response. */
- protected Assertion assertion;
-
- public ShibbolethSSORequestContext() {
- }
-
- public ShibbolethSSORequestContext(final ProfileRequest<ServletRequest> profileRequest,
- final ProfileResponse<ServletResponse> profileResponse, String shire, String target,
- String providerId, String remoteAddr) {
-
- this.profileRequest = profileRequest;
- this.profileResponse = profileResponse;
- this.servletRequest = (HttpServletRequest) profileRequest.getRawRequest();
- this.servletResponse = (HttpServletResponse) profileResponse.getRawResponse();
- this.shire = shire;
- this.target = target;
- this.providerId = providerId;
- this.remoteAddr = remoteAddr;
- }
-
- public ProfileRequest<ServletRequest> getProfileRequest() {
- return profileRequest;
- }
-
- public void setProfileRequest(ProfileRequest<ServletRequest> profileRequest) {
- this.profileRequest = profileRequest;
- this.servletRequest = (HttpServletRequest) profileRequest.getRawRequest();
- }
-
- public ProfileResponse<ServletResponse> getProfileResponse() {
- return profileResponse;
- }
-
- public void setProfileResponse(ProfileResponse<ServletResponse> profileResponse) {
- this.profileResponse = profileResponse;
- this.servletResponse = (HttpServletResponse) profileResponse.getRawResponse();
- }
-
- public HttpServletRequest getServletRequest() {
- return servletRequest;
- }
-
- public void setServletRequest(HttpServletRequest servletRequest) {
- this.servletRequest = servletRequest;
- }
-
- public HttpServletResponse getServletResponse() {
- return servletResponse;
- }
-
- public void setServletResponse(HttpServletResponse servletResponse) {
- this.servletResponse = servletResponse;
- }
-
- public String getShire() {
- return shire;
- }
-
- public void setShire(String shire) {
- this.shire = shire;
- }
-
- public String getTarget() {
- return target;
- }
-
- public void setTarget(String target) {
- this.target = target;
- }
-
- public String getProviderId() {
- return providerId;
- }
-
- public void setProviderId(String providerId) {
- this.providerId = providerId;
- }
-
- public String getRemoteAddr() {
- return remoteAddr;
- }
-
- public void setRemoteAddr(String remoteAddr) {
- this.remoteAddr = remoteAddr;
- }
-
- public LoginContext getLoginContex() {
- return loginContex;
- }
-
- public void setLoginContex(LoginContext loginContext) {
-
- this.loginContex = loginContext;
-
- if (loginContext.getProfileHandlerURL() == null) {
- loginContext.setProfileHandlerURL(getServletRequest().getRequestURI());
- }
-
- getHttpSession().setAttribute(LoginContext.LOGIN_CONTEXT_KEY, loginContext);
- }
-
- public RelyingPartyConfiguration getRpConfiguration() {
- return rpConfiguration;
- }
-
- public void setRpConfiguration(RelyingPartyConfiguration rpConfiguration) {
- this.rpConfiguration = rpConfiguration;
- }
-
- public Assertion getAssertion() {
- return assertion;
- }
-
- public void setAssertion(Assertion assertion) {
- this.assertion = assertion;
- }
-
- public ShibbolethSSOConfiguration getShibSSOConfiguration() {
- return shibSSOConfiguration;
- }
-
- public void setShibSSOConfiguration(ShibbolethSSOConfiguration shibSSOConfiguration) {
- this.shibSSOConfiguration = shibSSOConfiguration;
- }
-
- public SPSSODescriptor getSpDescriptor() {
- return spDescriptor;
- }
-
- public void setSpDescriptor(SPSSODescriptor spDescriptor) {
- this.spDescriptor = spDescriptor;
- }
-
- public AssertionConsumerService getAssertionConsumerService() {
- return assertionConsumerService;
- }
-
- public void setAssertionConsumerService(AssertionConsumerService assertionConsumers) {
- this.assertionConsumerService = assertionConsumers;
- }
-
-
- public HttpSession getHttpSession() {
-
- if (getServletRequest() != null) {
- return getServletRequest().getSession();
- } else {
- return null;
- }
- }
-
- public boolean equals(final Object obj) {
-
- if (obj == null) {
- return false;
- }
-
- if (getClass() != obj.getClass()) {
- return false;
- }
-
- final ShibbolethSSORequestContext other = (ShibbolethSSORequestContext) obj;
-
- if (servletRequest != other.servletRequest && (servletRequest == null || !this.servletRequest.equals(other.servletRequest))) {
- return false;
- }
-
- if (servletResponse != other.servletResponse && (servletResponse == null || !this.servletResponse.equals(other.servletResponse))) {
- return false;
- }
-
- if (shire != other.shire && (shire == null || !shire.equals(other.shire))) {
- return false;
- }
-
- if (target != other.target && (target == null || !target.equals(other.target))) {
- return false;
- }
-
- if (providerId != other.providerId && (providerId == null || !providerId.equals(other.providerId))) {
- return false;
- }
-
- if (remoteAddr != other.remoteAddr && (remoteAddr == null || !remoteAddr.equals(other.remoteAddr))) {
- return false;
- }
-
- return true;
- }
-
- public int hashCode() {
-
- int hash = 7;
- hash = 71 * hash + shire != null ? shire.hashCode() : 0;
- hash = 71 * hash + target != null ? target.hashCode() : 0;
- hash = 71 * hash + providerId != null ? providerId.hashCode() : 0;
- hash = 71 * hash + remoteAddr != null ? remoteAddr.hashCode() : 0;
-
- return hash;
- }
- }
-
- /**
- * Internal exception class used by utilty methods.
- */
- protected class ShibbolethSSOException extends Exception {
-
- public ShibbolethSSOException() {
- }
-
- public ShibbolethSSOException(final String message) {
- super(message);
- }
-
- public ShibbolethSSOException(final Throwable cause) {
- super(cause);
- }
-
- public ShibbolethSSOException(final String message, final Throwable cause) {
- super(message, cause);
- }
-
- }
-
-
- /** log4j. */
- private static final Logger log = Logger.getLogger(ShibbolethSSO.class);
-
- /** SAML 1 bearer confirmation method URI. */
- protected static final String BEARER_CONF_METHOD_URI = "urn:oasis:names:tc:SAML:1.0:cm:bearer";
-
- /** SAML 1 artifact confirmation method URI */
- protected static final String ARTIFACT_CONF_METHOD_URI = "urn:oasis:names:tc:SAML:1.0:cm:artifact";
-
- /** SAML 1.1 SPSSO protocol URI */
- protected static final String SAML11_PROTOCOL_URI = "urn:oasis:names:tc:SAML:1.1:protocol";
-
- /** SAML 1 Browser/POST protocol URI. */
- protected static final String PROFILE_BROWSER_POST_URI = "urn:oasis:names:tc:SAML:1.0:profiles:browser-post";
-
- /** SAML 1 Artifact protocol URI. */
- protected static final String PROFILE_ARTIFACT_URI = "urn:oasis:names:tc:SAML:1.0:profiles:artifact-01";
-
- /** The digest algorithm for generating SP cookies. */
- protected static final String RP_COOKIE_DIGEST_ALG = "SHA-1";
-
- /** Profile ID for this handler. */
- protected static final String PROFILE_ID = "urn:mace:shibboleth:1.0:profiles:AuthnRequest";
-
- /** The request parameter containing the time the request was made. */
- protected static final String REQUEST_PARAMETER_TIME = "time";
-
- /** HttpSession key for the ShibbolethSSORequestContext. */
- protected static final String REQUEST_CONTEXT_SESSION_KEY = "edu.internet2.middleware.shibboleth.idp.profile.saml1.ShibbolethSSORequestContext";
-
- /** The path to the IdP's AuthenticationManager servlet */
- protected String authnMgrURL;
-
- /** The URI of the default authentication method */
- protected String authenticationMethodURI;
-
- /** Builder for AuthenticationStatement objects. */
- protected SAMLObjectBuilder<AuthenticationStatement> authnStmtBuilder;
-
- /** Builder for Subject elements. */
- protected SAMLObjectBuilder<Subject> subjectBuilder;
-
- /** Builder for SubjectConfirmation objects. */
- protected SAMLObjectBuilder<SubjectConfirmation> subjConfBuilder;
-
- /** Builder for SubjectConfirmationMethod objects. */
- protected SAMLObjectBuilder<ConfirmationMethod> confMethodBuilder;
-
- /** Builder for NameIdentifiers. */
- protected SAMLObjectBuilder<NameIdentifier> nameIdentifierBuilder;
-
- /** Builder for Audience elements. */
- protected SAMLObjectBuilder<Audience> audienceBuilder;
-
- /** Builder for AudienceRestrictionCondition elements. */
- protected SAMLObjectBuilder<AudienceRestrictionCondition> audienceRestrictionBuilder;
-
- /** Builder for Assertions. */
- protected SAMLObjectBuilder<Assertion> assertionBuilder;
-
- /** Builder for Response objects. */
- protected SAMLObjectBuilder<Response> responseBuilder;
-
- /** Block stale requests. */
- protected boolean blockStaleRequests = false;
-
- /**
- * Time after which an authn request is considered stale (in seconds). Defaults to 30 minutes.
- */
- protected int requestTTL = 1800;
-
- /**
- * Default constructor.
- */
- public ShibbolethSSO() {
-
- // setup SAML object builders
-
- assertionBuilder = (SAMLObjectBuilder<Assertion>) getBuilderFactory().getBuilder(Assertion.DEFAULT_ELEMENT_NAME);
- authnStmtBuilder = (SAMLObjectBuilder<AuthenticationStatement>) getBuilderFactory().getBuilder(AuthenticationStatement.DEFAULT_ELEMENT_NAME);
- subjectBuilder = (SAMLObjectBuilder<Subject>) getBuilderFactory().getBuilder(Subject.DEFAULT_ELEMENT_NAME);
- subjConfBuilder = (SAMLObjectBuilder<SubjectConfirmation>) getBuilderFactory().getBuilder(SubjectConfirmation.DEFAULT_ELEMENT_NAME);
- confMethodBuilder = (SAMLObjectBuilder<ConfirmationMethod>) getBuilderFactory().getBuilder(ConfirmationMethod.DEFAULT_ELEMENT_NAME);
- nameIdentifierBuilder = (SAMLObjectBuilder<NameIdentifier>) getBuilderFactory().getBuilder(NameIdentifier.DEFAULT_ELEMENT_NAME);
- audienceBuilder = (SAMLObjectBuilder<Audience>) getBuilderFactory().getBuilder(Audience.DEFAULT_ELEMENT_NAME);
- audienceRestrictionBuilder = (SAMLObjectBuilder<AudienceRestrictionCondition>) getBuilderFactory().getBuilder(AudienceRestrictionCondition.DEFAULT_ELEMENT_NAME);
- responseBuilder = (SAMLObjectBuilder<Response>) getBuilderFactory().getBuilder(Response.DEFAULT_ELEMENT_NAME);
-
- }
-
- /** {@inheritDoc} */
- public String getProfileId() {
- return PROFILE_ID;
- }
-
- /**
- * Set the authentication manager.
- *
- * @param authnManagerURL The URL of the IdP's AuthenticationManager servlet
- */
- public void setAuthenticationManager(String authnManagerURL) {
- authnMgrURL = authnManagerURL;
- }
-
- /**
- * Set the authentication method URI.
- *
- * The URI SHOULD come from oasis-sstc-saml-core-1.1, section 7.1
- *
- * @param authMethod The authentication method's URI
- */
- public void setAuthenticationMethodURI(String authMethod) {
- authenticationMethodURI = authMethod;
- }
-
- /**
- * Set if old requests should be blocked.
- *
- * @param blockStaleRequests boolean flag.
- */
- public void setBlockStaleRequests(boolean blockStaleRequests) {
- this.blockStaleRequests = blockStaleRequests;
- }
-
- /**
- * Return if stale requests are blocked.
- *
- * @return <code>true</code> if old requests are blocked.
- */
- public boolean getBlockStaleRequests() {
- return blockStaleRequests;
- }
-
- /**
- * Set request TTL.
- *
- * @param ttl Request timeout (in seconds).
- */
- public void setRequestTTL(int ttl) {
- requestTTL = ttl;
- }
-
- /**
- * Get Request TTL. This is the time after which a request is considered stale.
- *
- * @return request timeout (in seconds).
- */
- public int getRequestTTL() {
- return requestTTL;
- }
-
- /** {@inheritDoc} */
- public void processRequest(final ProfileRequest<ServletRequest> request, final ProfileResponse<ServletResponse> response) throws ProfileException {
-
- // Only http servlets are supported for now.
- if (!(request.getRawRequest() instanceof HttpServletRequest)) {
- log.error("Received a non-HTTP request.");
- throw new ProfileException("Received a non-HTTP request.");
- }
-
- // This method is called twice.
- // On the first time, there will be no ShibbolethSSORequestContext object. We redirect control to the
- // AuthenticationManager to authenticate the user. The AuthenticationManager then redirects control
- // back to this servlet. On the "return leg" connection, there will be a ShibbolethSSORequestContext object.
-
- HttpServletRequest req = (HttpServletRequest) request.getRawRequest();
- Object o = req.getSession().getAttribute(REQUEST_CONTEXT_SESSION_KEY);
- if (o != null && !(o instanceof ShibbolethSSORequestContext)) {
- log.error("SAML 1 Authentication Request Handler: Invalid session data found for ShibbolethSSORequestContext");
- throw new ProfileException("SAML 1 Authentication Request Handler: Invalid session data found for ShibbolethSSORequestContext");
- }
-
- if (o == null) {
- setupNewRequest(request, response);
- } else {
-
- ShibbolethSSORequestContext requestContext = (ShibbolethSSORequestContext)o;
-
- // clean up the HttpSession.
- requestContext.getHttpSession().removeAttribute(REQUEST_CONTEXT_SESSION_KEY);
- requestContext.getHttpSession().removeAttribute(LoginContext.LOGIN_CONTEXT_KEY);
-
- finishProcessingRequest(requestContext);
- }
- }
-
- /**
- * Begin processing a SAML 1.x authentication request.
- * This ensurues that the request is well-formed and that
- * appropriate metadata can be found for the SP.
- * Once these conditions are met, control is passed to
- * the AuthenticationManager to authenticate the user.
- *
- * @param request The ProfileRequest.
- * @param response The ProfileResponse.
- *
- * @throws ProfileException On error.
- */
- protected void setupNewRequest(final ProfileRequest<ServletRequest> request, final ProfileResponse<ServletResponse> response) throws ProfileException {
-
- try {
- ShibbolethSSORequestContext requestContext = new ShibbolethSSORequestContext();
- requestContext.setProfileRequest(request);
- requestContext.setProfileResponse(response);
-
- // extract the (mandatory) request parameters.
- getRequestParameters(requestContext);
-
- // check that we have metadata for the SP
- validateRequestAgainstMetadata(requestContext);
-
- // check for stale requests
- if (blockStaleRequests) {
- String cookieName = getRPCookieName(requestContext.getProviderId());
- if (!validateFreshness(requestContext, cookieName)) {
- log.error("SAML 1 Authentication Request Handler: detected stale authentiation request");
- throw new ProfileException("SAML 1 Authentication Request Handler: detected stale authentication request");
- }
-
- writeFreshnessCookie(requestContext, cookieName);
- }
-
- // don't force reauth or passive auth
- requestContext.setLoginContex(new LoginContext(false, false));
-
- try {
- // put the request context object in the HttpSession, so we can retrieve it on the "return leg"
- requestContext.getHttpSession().setAttribute(REQUEST_CONTEXT_SESSION_KEY, requestContext);
-
- // the AuthenticationManager expects the LoginContext to be in the HttpSession too.
- requestContext.getHttpSession().setAttribute(LoginContext.LOGIN_CONTEXT_KEY, requestContext.getLoginContex());
-
- // forward control to the AuthenticationManager
- RequestDispatcher dispatcher = requestContext.getServletRequest().getRequestDispatcher(authnMgrURL);
- dispatcher.forward(requestContext.getServletRequest(), requestContext.getServletResponse());
- } catch (IOException ex) {
- log.error("SAML 1 Authentication Request Handler: Error forwarding SAML 1 SSO request to AuthenticationManager", ex);
- throw new ProfileException("Error forwarding SAML 1 SSO request to AuthenticationManager", ex);
- } catch (ServletException ex) {
- log.error("SAML 1 Authentication Request Handler: Error forwarding SAML 1 SSO request to AuthenticationManager", ex);
- throw new ProfileException("Error forwarding SAML 1 SSO request to AuthenticationManager", ex);
- }
-
- } catch (ShibbolethSSOException ex) {
- log.error("SAML 1 Authentication Request Handler: Error processing Shibboleth SSO request", ex);
- throw new ProfileException("Error processing Shibboleth SSO request", ex);
- }
- }
-
-
- /**
- * Process the "return leg" of a SAML 1 authentication request.
- *
- * This evaluates the AuthenticationManager's LoginContext, and generates an Authentication Assertion, as appropriate.
- *
- * @param requestContext The context for the request.
- *
- * @throws ProfileException On error.
- */
- protected void finishProcessingRequest(final ShibbolethSSORequestContext requestContext) throws ProfileException {
-
- // If the user successfully authenticated
- // build the appropriate AuthenticationStatement.
- if (requestContext.getLoginContex().getAuthenticationOK()) {
- DateTime now = new DateTime();
- generateAuthenticationAssertion(requestContext, now);
- }
-
- encodeSAMLResponse(requestContext);
- }
-
- /**
- * Encode the SAML response.
- *
- * @param requestContext The context for the request.
- *
- * @throws ProfileException On error.
- */
- protected void encodeSAMLResponse(final ShibbolethSSORequestContext requestContext) throws ProfileException {
-
- Response samlResponse = responseBuilder.buildObject();
- samlResponse.setID(getIdGenerator().generateIdentifier());
- samlResponse.setIssueInstant(new DateTime());
- samlResponse.setVersion(SAML_VERSION);
- samlResponse.setRecipient(requestContext.getProviderId());
-
- Status status;
-
- // If AuthN failed, and if we're using the Artifact binding, we don't send a failure message.
- if (!(requestContext.getLoginContex().getAuthenticationOK())
- && (requestContext.getAssertionConsumerService().getBinding().equals(PROFILE_ARTIFACT_URI))) {
-
- log.error("SAML 1 Authentication Request Handler: Authentication failed but using the Artifact binding for SP " +
- requestContext.getProviderId());
- return;
- }
-
- if (requestContext.getLoginContex().getAuthenticationOK()) {
- status = buildStatus("Success", null);
- List<Assertion> assertionList = samlResponse.getAssertions();
- assertionList.add(requestContext.getAssertion());
- } else {
- status = buildStatus("Responder", null);
- }
-
- samlResponse.setStatus(status);
-
- encodeResponse(PROFILE_ID, requestContext.getProfileResponse(), samlResponse,
- requestContext.getRpConfiguration(), requestContext.getSpDescriptor(),
- (Endpoint) requestContext.getAssertionConsumerService());
- }
-
- /**
- * Get the Shibboleth profile-specific request parameters.
- *
- * @param request The servlet request from the SP.
- * @param response The servlet response.
- *
- * @throw ShibbolethSSOException On Error.
- */
- protected void getRequestParameters(final ShibbolethSSORequestContext requestContext) throws ShibbolethSSOException {
-
- HttpServletRequest servletRequest = requestContext.getServletRequest();
-
- String target = servletRequest.getParameter("target");
- String providerId = servletRequest.getParameter("providerId");
- String shire = servletRequest.getParameter("shire");
- String remoteAddr = servletRequest.getRemoteAddr();
-
- if (target == null || target.equals("")) {
- log.error("SAML 1 Authentication Request Handler: Shib 1 SSO request is missing or contains an invalid target parameter");
- throw new ShibbolethSSOException("Shib 1 SSO request is missing or contains an invalid target parameter");
- }
-
- if (providerId == null || providerId.equals("")) {
- log.error("SAML 1 Authentication Request Handler: Shib 1 SSO request is missing or contains an invalid provierId parameter");
- throw new ShibbolethSSOException("Shib 1 SSO request is missing or contains an invalid provierId parameter");
- }
-
- if (shire == null || providerId.equals("")) {
- log.error("SAML 1 Authentication Request Handler: Shib 1 SSO request is missing or contains an invalid shire parameter");
- throw new ShibbolethSSOException("Shib 1 SSO request is missing or contains an invalid shire parameter");
- }
-
- if (remoteAddr == null || remoteAddr.equals("")) {
- log.error("SAML 1 Authentication Request Handler: Unable to obtain requestor address when processing Shib 1 SSO request");
- throw new ShibbolethSSOException("Unable to obtain requestor address when processing Shib 1 SSO request");
- }
-
- requestContext.setTarget(target);
- requestContext.setProviderId(providerId);
- requestContext.setShire(shire);
- requestContext.setRemoteAddr(remoteAddr);
- }
-
- /**
- * Generate a SAML 1 AuthenticationStatement.
- *
- * @param requestContext The context for the ShibbolethSSO request.
- * @param now The current timestamp
- *
- * @return A SAML 1 Authentication Assertion or <code>null</code> on error.
- */
- protected Assertion generateAuthenticationAssertion(final ShibbolethSSORequestContext requestContext,
- final DateTime now) {
-
- String providerId = requestContext.getRpConfiguration().getProviderId();
-
- Assertion authenticationAssertion = assertionBuilder.buildObject();
- authenticationAssertion.setIssueInstant(now);
- authenticationAssertion.setVersion(SAML_VERSION);
- authenticationAssertion.setIssuer(providerId);
- authenticationAssertion.setID(getIdGenerator().generateIdentifier());
-
- Conditions conditions = authenticationAssertion.getConditions();
- conditions.setNotBefore(now.minusSeconds(30)); // for now, clock skew is hard-coded to 30 seconds.
- conditions.setNotOnOrAfter(now.plusMillis((int)requestContext.getShibSSOConfiguration().getAssertionLifetime()));
-
- List<AudienceRestrictionCondition> audienceRestrictions = conditions.getAudienceRestrictionConditions();
- AudienceRestrictionCondition restrictionCondition = audienceRestrictionBuilder.buildObject();
- audienceRestrictions.add(restrictionCondition);
-
- // add the RelyingParty to the audience.
- Audience rpAudience = audienceBuilder.buildObject();
- rpAudience.setUri(requestContext.getRpConfiguration().getProviderId());
- restrictionCondition.getAudiences().add(rpAudience);
-
- // if necessary, explicitely add the SP to the audience.
- if (!providerId.equals(requestContext.getProviderId())) {
- Audience spAudience = (Audience) audienceBuilder.buildObject();
- spAudience.setUri(requestContext.getProviderId());
- restrictionCondition.getAudiences().add(spAudience);
- }
-
- AuthenticationStatement authenticationStatement = authnStmtBuilder.buildObject();
- authenticationStatement.setSubject(buildSubject(requestContext));
- authenticationStatement.setAuthenticationInstant(requestContext.getLoginContex().getAuthenticationInstant());
- authenticationStatement.setAuthenticationMethod(authenticationMethodURI);
-
- authenticationAssertion.getAuthenticationStatements().add(authenticationStatement);
-
- if (requestContext.getSpDescriptor().getWantAssertionsSigned()) {
- signAssertion(authenticationAssertion, requestContext.getRpConfiguration(), requestContext.getShibSSOConfiguration());
- }
-
- return authenticationAssertion;
- }
-
-
- /**
- * Ensure that metadata can be found for the authentication request.
- * If found, the request context is updated to reflect the appropriate entries.
- *
- * @param requestContext The context for the current request.
- *
- * @throws ShibbolethSSOException On error.
- */
- protected void validateRequestAgainstMetadata(final ShibbolethSSORequestContext requestContext) throws ShibbolethSSOException {
-
- RelyingPartyConfiguration relyingParty = getRelyingPartyConfigurationManager().getRelyingPartyConfiguration(requestContext.getProviderId());
- ProfileConfiguration temp = relyingParty.getProfileConfigurations().get(ShibbolethSSOConfiguration.PROFILE_ID);
- if (temp == null) {
- log.error("SAML 1 Authentication Request Handler: No profile configuration registered for " + ShibbolethSSOConfiguration.PROFILE_ID);
- throw new ShibbolethSSOException("No profile configuration registered for " + ShibbolethSSOConfiguration.PROFILE_ID);
- }
-
- ShibbolethSSOConfiguration ssoConfig = (ShibbolethSSOConfiguration) temp;
- SPSSODescriptor spDescriptor;
-
- try {
- spDescriptor = getMetadataProvider().getEntityDescriptor(relyingParty.getRelyingPartyId()).getSPSSODescriptor(SAML11_PROTOCOL_URI);
- } catch (MetadataProviderException ex) {
- log.error("SAML 1 Authentication Request Handler: Unable to locate metadata for SP " + requestContext.getProviderId() + " for protocol " + SAML11_PROTOCOL_URI, ex);
- throw new ShibbolethSSOException("Unable to locate metadata for SP " + requestContext.getProviderId() + " for protocol " + SAML11_PROTOCOL_URI, ex);
- }
-
- if (spDescriptor == null) {
- log.error("SAML 1 Authentication Request Handler: Unable to locate metadata for SP " + requestContext.getProviderId() + " for protocol " + SAML11_PROTOCOL_URI);
- throw new ShibbolethSSOException("Unable to locate metadata for SP " + requestContext.getProviderId() + " for protocol " + SAML11_PROTOCOL_URI);
- }
-
-
- // validate the AssertionConsumer ("shire") URL against the AssertionConsumerService endpoints in the metadata.
- if (!(evaluateACSEndpoint(requestContext, requestContext.getSpDescriptor().getDefaultAssertionConsumerService()))) {
-
- // if the default AssertionConsumerService endpoint was not valid, iterate over all remaining endpoints.
- boolean found = false;
- for (AssertionConsumerService candidateEndpoint : requestContext.getSpDescriptor().getAssertionConsumerServices()) {
- if (evaluateACSEndpoint(requestContext, candidateEndpoint)) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- log.error("SAML 1 Authentication Request Handler: Unable to find AssertionConsumerService " +
- requestContext.getShire() + " for SP " + requestContext.getProviderId() +
- " for protocol " + SAML11_PROTOCOL_URI);
- throw new ShibbolethSSOException("Unable to find AssertionConsumerService " +
- requestContext.getShire() + " for SP " + requestContext.getProviderId() +
- " for protocol " + SAML11_PROTOCOL_URI);
- }
- }
-
-
- // spDescriptor returns a reference to an internal mutable copy, so make a copy of it.
- List<AssertionConsumerService> consumerURLs =
- new ArrayList<AssertionConsumerService>(requestContext.getSpDescriptor().getAssertionConsumerServices().size());
-
- // filter out any list elements that don't have the correct location field.
- // copy any consumerURLs with the correct location
- for (AssertionConsumerService service : requestContext.getSpDescriptor().getAssertionConsumerServices()) {
- if (service.getLocation().equals(requestContext.getShire())) {
- consumerURLs.add(service);
- }
- }
- if (consumerURLs.size() == 0) {
- log.error("SAML 1 Authentication Request Handler: Unable to validate AssertionConsumerService URL against metadata: " + requestContext.getShire()
- + " not found for SP " + requestContext.getProviderId() + " for protocol " + SAML11_PROTOCOL_URI);
- throw new ShibbolethSSOException("Unable to validate AssertionConsumerService URL against metadata: " + requestContext.getShire()
- + " not found for SP " + requestContext.getProviderId() + " for protocol " + SAML11_PROTOCOL_URI);
- }
-
- requestContext.setRpConfiguration(relyingParty);
- requestContext.setShibSSOConfiguration(ssoConfig);
- requestContext.setSpDescriptor(spDescriptor);
- }
-
-
- /**
- * Evaluate a specific AssertionConsumerService endpoint against the request's "shire" parameter.
- * If it matches, update the request context to use this endpoint.
- *
- * @param requestContext The context for the current request.
- * @param candidateEndpoint An endpoint to consider for use for the response.
- *
- * @return <code>true</code> if <code>candidateEndpoint</code> is valid; otherwise, <code>false</code>.
- */
- protected boolean evaluateACSEndpoint(final ShibbolethSSORequestContext requestContext, final AssertionConsumerService candidateEndpoint) {
-
- if (requestContext.getShire().equals(candidateEndpoint.getLocation())) {
- requestContext.setAssertionConsumerService(candidateEndpoint);
- return true;
- } else {
- return false;
- }
- }
-
-
-
- /**
- * Validate the "freshness" of an authn request. If the reqeust is more than 30 minutes old, reject it.
- *
- * @param requestContext The context for the current request.
- * @param cookieName The name of the RP's cookie.
- *
- * @return <code>true</code> if the cookie is fresh; otherwise <code>false</code>
- *
- */
- protected boolean validateFreshness(final ShibbolethSSORequestContext requestContext, String cookieName) {
-
- if (cookieName == null) {
- return false;
- }
-
- String timestamp = requestContext.getServletRequest().getParameter(REQUEST_PARAMETER_TIME);
- if (timestamp == null || timestamp.equals("")) {
- return true;
- }
-
- long reqtime;
- try {
- reqtime = Long.parseLong(timestamp);
- } catch (NumberFormatException ex) {
- log.error("SAML 1 Authentication Request Handler: Unable to parse Authentication Request's timestamp", ex);
- return false;
- }
-
- if (reqtime * 1000 < (System.currentTimeMillis() - requestTTL * 1000)) {
- return false;
- }
-
- for (Cookie cookie : requestContext.getServletRequest().getCookies()) {
- if (cookieName.equals(cookie.getName())) {
- try {
- long cookieTime = Long.parseLong(cookie.getValue());
- if (reqtime <= cookieTime) {
- return false;
- }
- } catch (NumberFormatException ex) {
- log.error("SAML 1 Authentication Request Handler: Unable to parse freshness cookie's timestamp", ex);
- return false;
- }
- }
- }
-
- return true;
- }
-
- /**
- * Generate the RP's cookie name
- *
- * @param providerID The RP's providerID
- *
- * @throws ProfileException If unable to find a JCE provider for SHA-1
- *
- * @return the RP's cookie name
- */
- protected String getRPCookieName(String providerID) throws ProfileException {
-
- try {
- MessageDigest digester = MessageDigest.getInstance(RP_COOKIE_DIGEST_ALG);
- return "shib_sp_" + new String(Hex.encode(digester.digest(providerID.getBytes("UTF-8"))));
- } catch (NoSuchAlgorithmException ex) {
- throw new ProfileException("Unabel to create RPCookie", ex);
- } catch (UnsupportedEncodingException ex) {
- // this should never happen. UTF-8 encoding should always be supported.
- throw new ProfileException("Unable to locate UTF-8 encoder", ex);
- }
- }
-
- /**
- * Write the current time into the freshness cookie.
- *
- * @param requestContext The context for the current request.
- * @param cookieName The name of the cookie to write.
- */
- protected void writeFreshnessCookie(final ShibbolethSSORequestContext requestContext, String cookieName) {
-
- String timestamp = requestContext.getServletRequest().getParameter("time");
- if (timestamp == null || timestamp.equals("")) {
- return;
- }
-
- Cookie cookie = new Cookie(cookieName, timestamp);
- cookie.setSecure(true);
- requestContext.getServletResponse().addCookie(cookie);
- }
-
- /**
- * Generate a SAML 1 Subject element.
- *
- * @param requestContext The context for the current request.
- *
- * @return a Subject object.
- */
- protected Subject buildSubject(final ShibbolethSSORequestContext requestContext) {
-
- LoginContext loginContext = requestContext.getLoginContex();
- ShibbolethSSOConfiguration ssoConfig = requestContext.getShibSSOConfiguration();
-
- String protocolBinding = requestContext.getAssertionConsumerService().getBinding();
- String confirmationMethod = null;
-
- // Set the SubjectConfirmationMethod appropriately depending on the protocol binding
- if (protocolBinding.equals(PROFILE_ARTIFACT_URI)) {
- confirmationMethod = ARTIFACT_CONF_METHOD_URI;
- } else if (protocolBinding.equals(PROFILE_BROWSER_POST_URI)) {
- confirmationMethod = BEARER_CONF_METHOD_URI;
- }
-
- Subject subject = subjectBuilder.buildObject();
-
- NameIdentifier nameID = nameIdentifierBuilder.buildObject();
- nameID.setFormat(ssoConfig.getSubjectNameFormat());
-
- String username = loginContext.getUserID();
-
- // XXX: todo: map the username onto an appropriate format
- nameID.setNameQualifier(username);
-
- if (confirmationMethod != null) {
-
- ConfirmationMethod m = confMethodBuilder.buildObject();
- m.setConfirmationMethod(confirmationMethod);
-
- SubjectConfirmation subjConf = subjConfBuilder.buildObject();
- subjConf.getConfirmationMethods().add(m);
- subject.setSubjectConfirmation(subjConf);
- }
-
- return subject;
- }
-}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright [2007] [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.profile.saml1;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.log4j.Logger;
+import org.opensaml.common.SAMLObject;
+import org.opensaml.common.SAMLObjectBuilder;
+import org.opensaml.common.binding.BindingException;
+import org.opensaml.common.binding.encoding.MessageEncoder;
+import org.opensaml.saml1.core.AuthenticationStatement;
+import org.opensaml.saml1.core.Response;
+import org.opensaml.saml1.core.Statement;
+import org.opensaml.saml1.core.StatusCode;
+import org.opensaml.saml1.core.Subject;
+import org.opensaml.saml2.metadata.IDPSSODescriptor;
+import org.opensaml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.xml.util.DatatypeHelper;
+
+import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
+import edu.internet2.middleware.shibboleth.common.profile.ProfileRequest;
+import edu.internet2.middleware.shibboleth.common.profile.ProfileResponse;
+import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfiguration;
+import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml1.ShibbolethSSOConfiguration;
+import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
+import edu.internet2.middleware.shibboleth.idp.authn.ShibbolethSSOLoginContext;
+
+/** Shibboleth SSO request profile handler. */
+public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
+
+ /** Class logger. */
+ private final Logger log = Logger.getLogger(ShibbolethSSOProfileHandler.class);
+
+ /** Builder of AuthenticationStatement objects. */
+ private SAMLObjectBuilder<AuthenticationStatement> authnStatementBuilder;
+
+ /** URL of the authentication manager servlet. */
+ private String authenticationManagerPath;
+
+ /** Message encoder binding URI. */
+ private String encodingBinding;
+
+ /**
+ * Constructor.
+ *
+ * @param authnManagerPath path to the authentication manager servlet
+ * @param encoder URI of the encoding binding
+ *
+ * @throws IllegalArgumentException thrown if either the authentication manager path or encoding binding URI are
+ * null or empty
+ */
+ public ShibbolethSSOProfileHandler(String authnManagerPath, String encoder) {
+ if (DatatypeHelper.isEmpty(authnManagerPath) || DatatypeHelper.isEmpty(encoder)) {
+ throw new IllegalArgumentException("Authentication manager path and encoder binding URI may not be null");
+ }
+
+ authenticationManagerPath = authnManagerPath;
+ encodingBinding = encoder;
+
+ authnStatementBuilder = (SAMLObjectBuilder<AuthenticationStatement>) getBuilderFactory().getBuilder(
+ AuthenticationStatement.DEFAULT_ELEMENT_NAME);
+ }
+
+ /**
+ * Convenience method for getting the SAML 1 AuthenticationStatement builder.
+ *
+ * @return SAML 1 AuthenticationStatement builder
+ */
+ public SAMLObjectBuilder<AuthenticationStatement> getAuthenticationStatementBuilder() {
+ return authnStatementBuilder;
+ }
+
+ /** {@inheritDoc} */
+ public String getProfileId() {
+ return "urn:mace:shibboleth:2.0:idp:profiles:shibboleth:request:sso";
+ }
+
+ /** {@inheritDoc} */
+ public void processRequest(ProfileRequest<ServletRequest> request, ProfileResponse<ServletResponse> response)
+ throws ProfileException {
+
+ HttpSession httpSession = ((HttpServletRequest) request.getRawRequest()).getSession(true);
+ if (httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY) == null) {
+ performAuthentication(request, response);
+ } else {
+ completeAuthenticationRequest(request, response);
+ }
+ }
+
+ /**
+ * Creates a {@link LoginContext} an sends the request off to the AuthenticationManager to begin the process of
+ * authenticating the user.
+ *
+ * @param request current request
+ * @param response current response
+ *
+ * @throws ProfileException thrown if there is a problem creating the login context and transferring control to the
+ * authentication manager
+ */
+ protected void performAuthentication(ProfileRequest<ServletRequest> request,
+ ProfileResponse<ServletResponse> response) throws ProfileException {
+
+ HttpServletRequest httpRequest = (HttpServletRequest) request.getRawRequest();
+ HttpServletResponse httpResponse = (HttpServletResponse) response.getRawResponse();
+ HttpSession httpSession = httpRequest.getSession(true);
+
+ LoginContext loginContext = buildLoginContext(httpRequest);
+ httpSession.setAttribute(LoginContext.LOGIN_CONTEXT_KEY, loginContext);
+
+ try {
+ RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(authenticationManagerPath);
+ dispatcher.forward(httpRequest, httpResponse);
+ } catch (IOException ex) {
+ log.error("Error forwarding Shibboleth SSO request to AuthenticationManager", ex);
+ throw new ProfileException("Error forwarding Shibboleth SSO request to AuthenticationManager", ex);
+ } catch (ServletException ex) {
+ log.error("Error forwarding Shibboleth SSO request to AuthenticationManager", ex);
+ throw new ProfileException("Error forwarding Shibboleth SSO request to AuthenticationManager", ex);
+ }
+ }
+
+ /**
+ * 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 request current request
+ * @param response current response
+ *
+ * @throws ProfileException thrown if the response can not be created and sent back to the relying party
+ */
+ protected void completeAuthenticationRequest(ProfileRequest<ServletRequest> request,
+ ProfileResponse<ServletResponse> response) throws ProfileException {
+ HttpSession httpSession = ((HttpServletRequest) request.getRawRequest()).getSession(true);
+
+ ShibbolethSSOLoginContext loginContext = (ShibbolethSSOLoginContext) httpSession
+ .getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
+ httpSession.removeAttribute(LoginContext.LOGIN_CONTEXT_KEY);
+
+ ShibbolethSSORequestContext requestContext = buildRequestContext(loginContext, request, response);
+
+ Response samlResponse;
+ try {
+ if (!loginContext.getAuthenticationOK()) {
+ requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER, null, "User failed authentication"));
+ throw new ProfileException("User failed authentication");
+ }
+
+ ArrayList<Statement> statements = new ArrayList<Statement>();
+ statements.add(buildAuthenticationStatement(requestContext));
+ statements.add(buildAttributeStatement(requestContext, "urn:oasis:names:tc:SAML:1.0:cm:sender-vouches"));
+
+ samlResponse = buildResponse(requestContext, statements);
+ } catch (ProfileException e) {
+ samlResponse = buildErrorResponse(requestContext);
+ }
+
+ requestContext.setSamlResponse(samlResponse);
+ encodeResponse(requestContext);
+ writeAuditLogEntry(requestContext);
+ }
+
+ /**
+ * Creates a login context from the incoming HTTP request.
+ *
+ * @param request current HTTP request
+ *
+ * @return the constructed login context
+ *
+ * @throws ProfileException thrown if the incomming request did not contain a providerId, shire, and target
+ * parameter
+ */
+ protected ShibbolethSSOLoginContext buildLoginContext(HttpServletRequest request) throws ProfileException {
+ ShibbolethSSOLoginContext loginContext = new ShibbolethSSOLoginContext();
+
+ try {
+ String providerId = DatatypeHelper.safeTrimOrNullString(request.getParameter("providerId"));
+ if (providerId == null) {
+ log.error("No providerId parameter in Shibboleth SSO request");
+ throw new ProfileException("No providerId parameter in Shibboleth SSO request");
+ }
+ loginContext.setRelyingParty(URLDecoder.decode(providerId, "UTF-8"));
+
+ String acs = DatatypeHelper.safeTrimOrNullString(request.getParameter("shire"));
+ if (acs == null) {
+ log.error("No shire parameter in Shibboleth SSO request");
+ throw new ProfileException("No shire parameter in Shibboleth SSO request");
+ }
+ loginContext.setSpAssertionConsumerService(URLDecoder.decode(acs, "UTF-8"));
+
+ String target = DatatypeHelper.safeTrimOrNullString(request.getParameter("target"));
+ if (target == null) {
+ log.error("No target parameter in Shibboleth SSO request");
+ throw new ProfileException("No target parameter in Shibboleth SSO request");
+ }
+ loginContext.setSpTarget(URLDecoder.decode(target, "UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ // UTF-8 encoding required to be supported by all JVMs.
+ }
+
+ loginContext.setAuthenticationManagerURL(authenticationManagerPath);
+ loginContext.setProfileHandlerURL(request.getRequestURI());
+ return loginContext;
+ }
+
+ /**
+ * Creates an authentication request context from the current environmental information.
+ *
+ * @param loginContext current login context
+ * @param request current request
+ * @param response current response
+ *
+ * @return created authentication request context
+ */
+ protected ShibbolethSSORequestContext buildRequestContext(ShibbolethSSOLoginContext loginContext,
+ ProfileRequest<ServletRequest> request, ProfileResponse<ServletResponse> response) {
+ ShibbolethSSORequestContext requestContext = new ShibbolethSSORequestContext(request, response);
+
+ requestContext.setLoginContext(loginContext);
+
+ requestContext.setPrincipalName(loginContext.getUserID());
+
+ requestContext.setPrincipalAuthenticationMethod(loginContext.getAuthenticationMethod());
+
+ String relyingPartyId = loginContext.getRelyingPartyId();
+
+ requestContext.setRelyingPartyId(relyingPartyId);
+
+ RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(relyingPartyId);
+ requestContext.setRelyingPartyConfiguration(rpConfig);
+
+ requestContext.setRelyingPartyRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+
+ requestContext.setAssertingPartyId(requestContext.getRelyingPartyConfiguration().getProviderId());
+
+ requestContext.setAssertingPartyRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
+
+ requestContext.setProfileConfiguration((ShibbolethSSOConfiguration) rpConfig
+ .getProfileConfiguration(ShibbolethSSOConfiguration.PROFILE_ID));
+
+ return requestContext;
+ }
+
+ /**
+ * Builds the authentication statement for the authenticated principal.
+ *
+ * @param requestContext current request context
+ *
+ * @return the created statement
+ */
+ protected AuthenticationStatement buildAuthenticationStatement(ShibbolethSSORequestContext requestContext)
+ throws ProfileException {
+ ShibbolethSSOLoginContext loginContext = requestContext.getLoginContext();
+
+ AuthenticationStatement statement = getAuthenticationStatementBuilder().buildObject();
+ statement.setAuthenticationInstant(loginContext.getAuthenticationInstant());
+ statement.setAuthenticationMethod(loginContext.getAuthenticationMethod());
+
+ // TODO
+ statement.setSubjectLocality(null);
+
+ Subject statementSubject = buildSubject(requestContext, "urn:oasis:names:tc:SAML:1.0:cm:sender-vouches");
+ statement.setSubject(statementSubject);
+
+ return statement;
+ }
+
+ /**
+ * Encodes the request's SAML response and writes it to the servlet response.
+ *
+ * @param requestContext current request context
+ *
+ * @throws ProfileException thrown if no message encoder is registered for this profiles binding
+ */
+ protected void encodeResponse(ShibbolethSSORequestContext requestContext) throws ProfileException {
+ if (log.isDebugEnabled()) {
+ log.debug("Encoding response to SAML request from relying party " + requestContext.getRelyingPartyId());
+ }
+ MessageEncoder<ServletResponse> encoder = getMessageEncoderFactory().getMessageEncoder(encodingBinding);
+ if (encoder == null) {
+ throw new ProfileException("No response encoder was registered for binding type: " + encodingBinding);
+ }
+
+ super.populateMessageEncoder(encoder);
+ encoder.setResponse(requestContext.getProfileResponse().getRawResponse());
+ encoder.setSamlMessage(requestContext.getSamlResponse());
+ requestContext.setMessageEncoder(encoder);
+
+ try {
+ encoder.encode();
+ } catch (BindingException e) {
+ throw new ProfileException("Unable to encode response to relying party: "
+ + requestContext.getRelyingPartyId(), e);
+ }
+ }
+
+ /** Represents the internal state of a Shibboleth SSO Request while it's being processed by the IdP. */
+ protected class ShibbolethSSORequestContext extends
+ SAML1ProfileRequestContext<SAMLObject, Response, ShibbolethSSOConfiguration> {
+
+ /** Current login context. */
+ private ShibbolethSSOLoginContext loginContext;
+
+ /**
+ * Constructor.
+ *
+ * @param request current profile request
+ * @param response current profile response
+ */
+ public ShibbolethSSORequestContext(ProfileRequest<ServletRequest> request,
+ ProfileResponse<ServletResponse> response) {
+ super(request, response);
+ }
+
+ /**
+ * Gets the current login context.
+ *
+ * @return current login context
+ */
+ public ShibbolethSSOLoginContext getLoginContext() {
+ return loginContext;
+ }
+
+ /**
+ * Sets the current login context.
+ *
+ * @param context current login context
+ */
+ public void setLoginContext(ShibbolethSSOLoginContext context) {
+ loginContext = context;
+ }
+ }
+}
\ No newline at end of file
import edu.internet2.middleware.shibboleth.idp.session.ServiceInformation;
import edu.internet2.middleware.shibboleth.idp.session.Session;
-/**
- * Common implementation details for profile handlers.
- */
+/** Common implementation details for profile handlers. */
public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHandler {
/** SAML Version for this profile handler. */
AbstractSAML2ProfileConfiguration profileConfiguration = requestContext.getProfileConfiguration();
SAML2AttributeAuthority attributeAuthority = profileConfiguration.getAttributeAuthority();
- if (log.isDebugEnabled()) {
- log.debug("Resolving principal name for subject of SAML request " + requestContext.getSamlRequest().getID()
- + " from relying party " + requestContext.getRelyingPartyId());
- }
-
try {
if (log.isDebugEnabled()) {
log.debug("Resolving attributes for principal " + requestContext.getPrincipalName()
import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfiguration;
import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml2.AttributeQueryConfiguration;
-/**
- * SAML 2.0 Attribute Query profile handler.
- */
+/** SAML 2.0 Attribute Query profile handler. */
public class AttributeQueryProfileHandler extends AbstractSAML2ProfileHandler {
/** Class logger. */
Response samlResponse;
try {
decodeRequest(requestContext);
+
+ // Resolve attribute query name id to principal name and place in context
+ resolvePrincipal(requestContext);
// Lookup principal name and attributes, create attribute statement from information
ArrayList<Statement> statements = new ArrayList<Statement>();
import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
import edu.internet2.middleware.shibboleth.idp.authn.Saml2LoginContext;
-/**
- * SAML 2.0 authentication request profile handler.
- */
+/** SAML 2.0 SSO request profile handler. */
public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
/** Class logger. */
authnContextDeclRefBuilder = (SAMLObjectBuilder<AuthnContextDeclRef>) getBuilderFactory().getBuilder(
AuthnContextDeclRef.DEFAULT_ELEMENT_NAME);
}
+
+ /**
+ * Convenience method for getting the SAML 2 AuthnStatement builder.
+ *
+ * @return SAML 2 AuthnStatement builder
+ */
+ public SAMLObjectBuilder<AuthnStatement> getAuthnStatementBuilder(){
+ return authnStatementBuilder;
+ }
+
+ /**
+ * Convenience method for getting the SAML 2 AuthnContext builder.
+ *
+ * @return SAML 2 AuthnContext builder
+ */
+ public SAMLObjectBuilder<AuthnContext> getAuthnContextBuilder(){
+ return authnContextBuilder;
+ }
+
+ /**
+ * Convenience method for getting the SAML 2 AuthnContextClassRef builder.
+ *
+ * @return SAML 2 AuthnContextClassRef builder
+ */
+ public SAMLObjectBuilder<AuthnContextClassRef> getAuthnContextClassRefBuilder(){
+ return authnContextClassRefBuilder;
+ }
+
+ /**
+ * Convenience method for getting the SAML 2 AuthnContextDeclRef builder.
+ *
+ * @return SAML 2 AuthnContextDeclRef builder
+ */
+ public SAMLObjectBuilder<AuthnContextDeclRef> getAuthnContextDeclRefBuilder(){
+ return authnContextDeclRefBuilder;
+ }
/** {@inheritDoc} */
public String getProfileId() {
- return "urn:mace:shibboleth:2.0:idp:profiles:saml2:request:authentication";
+ return "urn:mace:shibboleth:2.0:idp:profiles:saml2:request:sso";
}
/** {@inheritDoc} */
authnRequest = (AuthnRequest) decoder.getSAMLMessage();
Saml2LoginContext loginContext = new Saml2LoginContext(relyingParty, authnRequest);
+ loginContext.setAuthenticationManagerURL(authenticationManagerPath);
loginContext.setProfileHandlerURL(httpRequest.getRequestURI());
HttpSession httpSession = httpRequest.getSession();
ProfileResponse<ServletResponse> response) throws ProfileException {
HttpSession httpSession = ((HttpServletRequest) request.getRawRequest()).getSession(true);
+
Saml2LoginContext loginContext = (Saml2LoginContext) httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
- AuthenticationRequestContext requestContext = buildRequestContext(loginContext, request, response);
+ httpSession.removeAttribute(LoginContext.LOGIN_CONTEXT_KEY);
+
+ SSORequestContext requestContext = buildRequestContext(loginContext, request, response);
Response samlResponse;
try {
*
* @throws ProfileException thrown if there is a problem creating the context
*/
- protected AuthenticationRequestContext buildRequestContext(Saml2LoginContext loginContext,
+ protected SSORequestContext buildRequestContext(Saml2LoginContext loginContext,
ProfileRequest<ServletRequest> request, ProfileResponse<ServletResponse> response) throws ProfileException {
- AuthenticationRequestContext requestContext = new AuthenticationRequestContext(request, response);
+ SSORequestContext requestContext = new SSORequestContext(request, response);
try {
String relyingPartyId = loginContext.getRelyingPartyId();
*
* @return constructed authentication statement
*/
- protected AuthnStatement buildAuthnStatement(AuthenticationRequestContext requestContext) {
+ protected AuthnStatement buildAuthnStatement(SSORequestContext requestContext) {
Saml2LoginContext loginContext = requestContext.getLoginContext();
AuthnContext authnContext = buildAuthnContext(requestContext);
- AuthnStatement statement = authnStatementBuilder.buildObject();
+ AuthnStatement statement = getAuthnStatementBuilder().buildObject();
statement.setAuthnContext(authnContext);
statement.setAuthnInstant(loginContext.getAuthenticationInstant());
*
* @return the built authn context
*/
- protected AuthnContext buildAuthnContext(AuthenticationRequestContext requestContext) {
- AuthnContext authnContext = authnContextBuilder.buildObject();
+ protected AuthnContext buildAuthnContext(SSORequestContext requestContext) {
+ AuthnContext authnContext = getAuthnContextBuilder().buildObject();
Saml2LoginContext loginContext = requestContext.getLoginContext();
AuthnRequest authnRequest = requestContext.getSamlRequest();
if (requestedAuthnContext.getAuthnContextClassRefs() != null) {
for (AuthnContextClassRef classRef : requestedAuthnContext.getAuthnContextClassRefs()) {
if (classRef.getAuthnContextClassRef().equals(loginContext.getAuthenticationMethod())) {
- AuthnContextClassRef ref = authnContextClassRefBuilder.buildObject();
+ AuthnContextClassRef ref = getAuthnContextClassRefBuilder().buildObject();
ref.setAuthnContextClassRef(loginContext.getAuthenticationMethod());
authnContext.setAuthnContextClassRef(ref);
}
} else if (requestedAuthnContext.getAuthnContextDeclRefs() != null) {
for (AuthnContextDeclRef declRef : requestedAuthnContext.getAuthnContextDeclRefs()) {
if (declRef.getAuthnContextDeclRef().equals(loginContext.getAuthenticationMethod())) {
- AuthnContextDeclRef ref = authnContextDeclRefBuilder.buildObject();
+ AuthnContextDeclRef ref = getAuthnContextDeclRefBuilder().buildObject();
ref.setAuthnContextDeclRef(loginContext.getAuthenticationMethod());
authnContext.setAuthnContextDeclRef(ref);
}
}
}
} else {
- AuthnContextDeclRef ref = authnContextDeclRefBuilder.buildObject();
+ AuthnContextDeclRef ref = getAuthnContextDeclRefBuilder().buildObject();
ref.setAuthnContextDeclRef(loginContext.getAuthenticationMethod());
authnContext.setAuthnContextDeclRef(ref);
}
*
* @throws ProfileException thrown if no message encoder is registered for this profiles binding
*/
- protected void encodeResponse(AuthenticationRequestContext requestContext) throws ProfileException {
+ protected void encodeResponse(SSORequestContext requestContext) throws ProfileException {
if (log.isDebugEnabled()) {
log.debug("Encoding response to SAML request " + requestContext.getSamlRequest().getID()
+ " from relying party " + requestContext.getRelyingPartyId());
}
}
- /**
- * Represents the internal state of a SAML 2.0 Authentiation Request while it's being processed by the IdP.
- */
- protected class AuthenticationRequestContext extends
+ /** Represents the internal state of a SAML 2.0 SSO Request while it's being processed by the IdP. */
+ protected class SSORequestContext extends
SAML2ProfileRequestContext<AuthnRequest, Response, SSOConfiguration> {
/** Current login context. */
* @param request current profile request
* @param response current profile response
*/
- public AuthenticationRequestContext(ProfileRequest<ServletRequest> request,
+ public SSORequestContext(ProfileRequest<ServletRequest> request,
ProfileResponse<ServletResponse> response) {
super(request, response);
}