urn\:mace\:shibboleth\:2.0\:idp\:services = edu.internet2.middleware.shibboleth.idp.config.service.IdPServicesNamespaceHandler
-urn\:mace\:shibboleth\:2.0\:idp\:profile = edu.internet2.middleware.shibboleth.idp.config.profile.ProfileHandlerNamespaceHandler
\ No newline at end of file
+urn\:mace\:shibboleth\:2.0\:idp\:profile-handler = edu.internet2.middleware.shibboleth.idp.config.profile.ProfileHandlerNamespaceHandler
\ No newline at end of file
urn\:mace\:shibboleth\:2.0\:idp\:services = schema/shibboleth-2.0-idp-service.xsd
-urn\:mace\:shibboleth\:2.0\:idp\:profile = schema/shibboleth-2.0-idp-profile.xsd
\ No newline at end of file
+urn\:mace\:shibboleth\:2.0\:idp\:profile-handler = schema/shibboleth-2.0-idp-profile-handler.xsd
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
-<xsd:schema targetNamespace="urn:mace:shibboleth:2.0:idp:profile" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns="urn:mace:shibboleth:2.0:idp:profile" xmlns:service="urn:mace:shibboleth:2.0:services"
+<xsd:schema targetNamespace="urn:mace:shibboleth:2.0:idp:profile-handler" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns="urn:mace:shibboleth:2.0:idp:profile-handler" xmlns:service="urn:mace:shibboleth:2.0:services"
elementFormDefault="qualified">
<xsd:include schemaLocation="classpath:/schema/shibboleth-2.0-profile-handler.xsd" />
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
- <xsd:element name="ErrorHandler" type="ErrorHandlerType">
-
- </xsd:element>
- <xsd:element name="ProfileHandler" type="RequestHandlerType" minOccurs="0"
- maxOccurs="unbounded">
-
- </xsd:element>
+ <xsd:element name="ErrorHandler" type="ErrorHandlerType" />
+ <xsd:element name="ProfileHandler" type="RequestHandlerType" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="AuthenticationHandler" type="AuthenticationHandlerType" minOccurs="0"
- maxOccurs="unbounded">
-
- </xsd:element>
+ maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:complexContent>
</xsd:complexType>
+ <xsd:complexType name="RemoteUser">
+ <xsd:complexContent>
+ <xsd:extension base="AuthenticationHandlerType">
+ <xsd:attribute name="protectedServletPath" type="xsd:string" default="/Authn/RemoteUser">
+ <xsd:annotation>
+ <xsd:documentation>
+ The servlet context path to the
+ edu.internet2.middleware.shibboleth.idp.authn.provider.RemoteUserAuthServlet instance
+ protected by the container or web server.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
<xsd:complexType name="AuthenticationHandlerType" abstract="true">
-
+ <xsd:annotation>
+ <xsd:documentation>Base type for authentication handler types.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="AuthenticationMethod" type="xsd:string" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ The authentication methods supported by this handler. In SAML these methods represent the SAML 2
+ authentication contexts class and declaration reference URIs.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute name="authenticationDuration" type="xsd:positiveInteger" default="30">
+ <xsd:annotation>
+ <xsd:documentation>
+ The length of time, in minutes, that an authentication performed by this handler should be
+ considered active. After which time a user, previously authenticated by this handler, must
+ re-authenticate in order to assert the authentication method again.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
</xsd:complexType>
-
+
</xsd:schema>
\ 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.config.profile;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opensaml.xml.util.DatatypeHelper;
+import org.opensaml.xml.util.XMLHelper;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.w3c.dom.Element;
+
+/**
+ * Base class for authentication handler definition parsers.
+ */
+public abstract class AbstractAuthenticationHandlerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
+
+ /** {@inheritDoc} */
+ protected void doParse(Element config, BeanDefinitionBuilder builder) {
+ builder.addPropertyValue("authenticationDuration", Integer.parseInt(config.getAttributeNS(null,
+ "authenticationDuration")));
+
+ ArrayList<String> authnMethods = new ArrayList<String>();
+ List<Element> authnMethodElems = XMLHelper.getChildElementsByTagNameNS(config,
+ ProfileHandlerNamespaceHandler.NAMESPACE, "AuthenticationMethod");
+ for (Element authnMethodElem : authnMethodElems) {
+ authnMethods.add(DatatypeHelper.safeTrimOrNullString(authnMethodElem.getTextContent()));
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected boolean shouldGenerateId() {
+ return true;
+ }
+}
\ 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.config.profile;
+
+import java.util.List;
+
+import org.springframework.beans.factory.config.AbstractFactoryBean;
+
+import edu.internet2.middleware.shibboleth.idp.authn.provider.AbstractAuthenticationHandler;
+
+/**
+ * Base class for authentication handler factory beans.
+ */
+public abstract class AbstractAuthenticationHandlerFactoryBean extends AbstractFactoryBean {
+
+ /** Authentication methods supported by the handler. */
+ private List<String> authenticationMethods;
+
+ /** Duration of the authentication, in minutes. */
+ private int authenticationDuration;
+
+ /**
+ * Gets the duration of the authentication, in minutes.
+ *
+ * @return duration of the authentication, in minutes
+ */
+ public int getAuthenticationDuration() {
+ return authenticationDuration;
+ }
+
+ /**
+ * Sets the duration of the authentication, in minutes.
+ *
+ * @param duration duration of the authentication, in minutes
+ */
+ public void setAuthenticationDuration(int duration) {
+ this.authenticationDuration = duration;
+ }
+
+ /**
+ * Gets the authentication methods supported by the handler.
+ *
+ * @return authentication methods supported by the handler
+ */
+ public List<String> getAuthenticationMethods() {
+ return authenticationMethods;
+ }
+
+ /**
+ * Sets the authentication methods supported by the handler.
+ *
+ * @param methods authentication methods supported by the handler
+ */
+ public void setAuthenticationMethods(List<String> methods) {
+ this.authenticationMethods = methods;
+ }
+
+ /**
+ * Populates the authenication duration and methods of the handler.
+ *
+ * @param handler the authentication handler to populate
+ */
+ protected void populateHandler(AbstractAuthenticationHandler handler) {
+ if (authenticationMethods != null) {
+ handler.getSupportedAuthenticationMethods().addAll(authenticationMethods);
+ }
+ handler.setAuthenticationDurection(authenticationDuration * 60 * 1000);
+ }
+}
public class ProfileHandlerNamespaceHandler extends BaseSpringNamespaceHandler {
/** Namespace URI. */
- public static final String NAMESPACE = "urn:mace:shibboleth:2.0:idp:profile";
+ public static final String NAMESPACE = "urn:mace:shibboleth:2.0:idp:profile-handler";
/** {@inheritDoc} */
public void init() {
registerBeanDefinitionParser(SAML2SSOProfileHandlerBeanDefinitionParser.SCHEMA_TYPE,
new SAML2SSOProfileHandlerBeanDefinitionParser());
+
+ registerBeanDefinitionParser(RemoteUserAuthenticationHandlerBeanDefinitionParser.SCHEMA_TYPE,
+ new RemoteUserAuthenticationHandlerBeanDefinitionParser());
}
}
\ 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.config.profile;
+
+import javax.xml.namespace.QName;
+
+import org.opensaml.xml.util.DatatypeHelper;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.w3c.dom.Element;
+
+/**
+ * Spring bean definition parser for remote user authentication handlers.
+ */
+public class RemoteUserAuthenticationHandlerBeanDefinitionParser extends
+ AbstractAuthenticationHandlerBeanDefinitionParser {
+
+ /** Schema type. */
+ public static final QName SCHEMA_TYPE = new QName(ProfileHandlerNamespaceHandler.NAMESPACE, "RemoteUser");
+
+ /** {@inheritDoc} */
+ protected Class getBeanClass(Element arg0) {
+ return RemoteUserAuthenticationHandlerFactoryBean.class;
+ }
+
+ /** {@inheritDoc} */
+ protected void doParse(Element config, BeanDefinitionBuilder builder) {
+ super.doParse(config, builder);
+
+ builder.addPropertyValue("protectedServletPath", DatatypeHelper.safeTrimOrNullString(config.getAttributeNS(
+ null, "protectedServletPath")));
+ }
+}
\ 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.config.profile;
+
+import edu.internet2.middleware.shibboleth.idp.authn.provider.RemoteUserAuthenticationHandler;
+
+/**
+ * Spring factory for {@link RemoteUserAuthenticationHandler}.
+ */
+public class RemoteUserAuthenticationHandlerFactoryBean extends AbstractAuthenticationHandlerFactoryBean {
+
+ /** Path to protected servlet. */
+ private String protectedServletPath;
+
+ /** {@inheritDoc} */
+ public Class getObjectType() {
+ return RemoteUserAuthenticationHandler.class;
+ }
+
+ /**
+ * Gets the path to protected servlet.
+ *
+ * @return path to protected servlet
+ */
+ public String getProtectedServletPath() {
+ return protectedServletPath;
+ }
+
+ /**
+ * Sets the path to protected servlet.
+ *
+ * @param path Tpath to protected servlet
+ */
+ public void setProtectedServletPath(String path) {
+ this.protectedServletPath = path;
+ }
+
+ /** {@inheritDoc} */
+ protected Object createInstance() throws Exception {
+ RemoteUserAuthenticationHandler handler = new RemoteUserAuthenticationHandler();
+ handler.setServletURL(getProtectedServletPath());
+ populateHandler(handler);
+ return handler;
+ }
+}
\ No newline at end of file
*/
public class IdPProfileHandlerManager extends BaseReloadableService implements ProfileHandlerManager {
- /** URI of the default authentication method. */
- public static final String DEFAULT_AUTHEN_METHOD_URI = "urn:mace:shibboleth:2.0:idp:authentication:method:default";
-
/** Class logger. */
private final Logger log = Logger.getLogger(IdPProfileHandlerManager.class);
}
}
- Pair<String, AuthenticationHandler> authenticationHandler = new Pair<String, AuthenticationHandler>(
- DEFAULT_AUTHEN_METHOD_URI, authenticationHandlers.get(DEFAULT_AUTHEN_METHOD_URI));
- return authenticationHandler;
+ return null;
}
/**
* Builds a NameIdentifier appropriate for this request. NameIdentifier are built by inspecting the SAML request and
* metadata, picking a name format that was requested by the relying party or is mutually supported by both the
* relying party and asserting party as described in their metadata entries. Once a set of supported name formats is
- * determined the principals attributes are inspected for an attribtue supported an attribute encoder whose category
+ * determined the principals attributes are inspected for an attribute supported an attribute encoder whose category
* is one of the supported name formats.
*
* @param requestContext current request context
throw new ProfileException("No providerId parameter in Shibboleth SSO request");
}
loginContext.setRelyingParty(URLDecoder.decode(providerId, "UTF-8"));
+
+ RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(providerId);
+ if(rpConfig == null){
+ log.error("No relying party configuration available for " + providerId);
+ throw new ProfileException("No relying party configuration available for " + providerId);
+ }
+ loginContext.getRequestedAuthenticationMethods().add(rpConfig.getDefaultAuthenticationMethod());
String acs = DatatypeHelper.safeTrimOrNullString(request.getParameter("shire"));
if (acs == null) {
* Builds a NameID appropriate for this request. NameIDs are built by inspecting the SAML request and metadata,
* picking a name format that was requested by the relying party or is mutually supported by both the relying party
* and asserting party as described in their metadata entries. Once a set of supported name formats is determined
- * the principals attributes are inspected for an attribtue supported an attribute encoder whose category is one of
+ * the principals attributes are inspected for an attribute supported an attribute encoder whose category is one of
* the supported name formats.
*
* @param requestContext current request context
SAMLSecurityPolicy securityPolicy = decoder.getSecurityPolicy();
String relyingParty = securityPolicy.getIssuer();
+ RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(relyingParty);
+ if(rpConfig == null){
+ log.error("No relying party configuration for " + relyingParty);
+ throw new ProfileException("No relying party configuration for " + relyingParty);
+ }
+
authnRequest = (AuthnRequest) decoder.getSAMLMessage();
Saml2LoginContext loginContext = new Saml2LoginContext(relyingParty, authnRequest);
loginContext.setAuthenticationEngineURL(authenticationManagerPath);
loginContext.setProfileHandlerURL(httpRequest.getRequestURI());
+ if (loginContext.getRequestedAuthenticationMethods().size() == 0) {
+ loginContext.getRequestedAuthenticationMethods().add(rpConfig.getDefaultAuthenticationMethod());
+ }
HttpSession httpSession = httpRequest.getSession();
httpSession.setAttribute(Saml2LoginContext.LOGIN_CONTEXT_KEY, loginContext);
<?xml version="1.0" encoding="UTF-8"?>
-<ProfileHandlerGroup xmlns="urn:mace:shibboleth:2.0:idp:profile" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="urn:mace:shibboleth:2.0:idp:profile classpath:/schema/shibboleth-2.0-idp-profile.xsd">
+<ProfileHandlerGroup xmlns="urn:mace:shibboleth:2.0:idp:profile-handler" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:mace:shibboleth:2.0:idp:profile-handler classpath:/schema/shibboleth-2.0-idp-profile-handler.xsd">
<ErrorHandler xsi:type="JSPErrorHandler" jspPagePath="/error.jsp" />
securityPolicyFactoryId="shibboleth.SAML2SSOMessageSecurityPolicyFactoryIssuerAuth">
<RequestPath>/IdP/saml2/SSO</RequestPath>
</ProfileHandler>
+
+ <AuthenticationHandler xsi:type="RemoteUser">
+ <AuthenticationMethod>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</AuthenticationMethod>
+ <AuthenticationMethod>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</AuthenticationMethod>
+ </AuthenticationHandler>
</ProfileHandlerGroup>
\ No newline at end of file
Saml2LoginContext loginContext = new Saml2LoginContext("urn:example.org:unitTestFed:sp2", authnRequest);
loginContext.setAuthenticationInstant(new DateTime());
- loginContext.setAuthenticationMethod(IdPProfileHandlerManager.DEFAULT_AUTHEN_METHOD_URI);
+ loginContext.setAuthenticationMethod("urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified");
loginContext.setPrincipalAuthenticated(true);
loginContext.setPrincipalName("testUser");
protected String getSamlRequestString(AuthnRequest request) throws MarshallingException {
Marshaller marshaller = marshallerFactory.getMarshaller(request);
Element requestElem = marshaller.marshall(request);
- String requestString = XMLHelper.nodeToString(requestElem);
- return Base64.encodeBytes(requestString.getBytes());
+ return XMLHelper.nodeToString(requestElem);
}
}
\ No newline at end of file