Add configuration code for external authentication login handler - SIDP-448
authorlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Sun, 1 May 2011 18:16:58 +0000 (18:16 +0000)
committerlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Sun, 1 May 2011 18:16:58 +0000 (18:16 +0000)
Add a bit more logging to name identifier selection process
Update MDUI taglib to comply with JSP 2.0

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

src/installer/resources/conf-tmpl/handler.xml
src/main/java/edu/internet2/middleware/shibboleth/idp/authn/provider/ExternalAuthnSystemLoginHandler.java
src/main/java/edu/internet2/middleware/shibboleth/idp/config/profile/ProfileHandlerNamespaceHandler.java
src/main/java/edu/internet2/middleware/shibboleth/idp/config/profile/authn/ExternalAuthnSystemLoginHandlerBeanDefinitionParser.java [new file with mode: 0644]
src/main/java/edu/internet2/middleware/shibboleth/idp/config/profile/authn/ExternalAuthnSystemLoginHandlerFactoryBean.java [new file with mode: 0644]
src/main/java/edu/internet2/middleware/shibboleth/idp/profile/AbstractSAMLProfileHandler.java
src/main/resources/schema/shibboleth-2.0-idp-profile-handler.xsd
src/main/webapp/WEB-INF/mduitaglib.tld
src/main/webapp/WEB-INF/web.xml
src/main/webapp/error.jsp
src/main/webapp/login.jsp

index b9119cb..8d00f8a 100644 (file)
         <ph:AuthenticationMethod>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</ph:AuthenticationMethod>
     </ph:LoginHandler>
     
+    <!-- Login handler that delegates the act of authentication to an external system. -->
+    <!-- This login handler and the RemoteUser login handler will be merged in the next major release. -->
+    <!--
+    <ph:LoginHandler xsi:type="ph:ExternalAuthn">
+        <ph:AuthenticationMethod>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</ph:AuthenticationMethod>
+        <ph:QueryParam name="foo" value="bar" />
+    </ph:LoginHandler>
+    -->
+    
     <!--  Username/password login handler -->
     <!-- 
     <ph:LoginHandler xsi:type="ph:UsernamePassword" 
index 4c1fc46..decc572 100644 (file)
@@ -133,6 +133,10 @@ public class ExternalAuthnSystemLoginHandler extends AbstractLoginHandler {
      * @param params query parameters that will be sent to the SSO-protected Servlet, maybe null
      */
     public void setQueryParameters(Map<String, String> params) {
+        if(params == null || params.isEmpty()){
+            queryParameters = Collections.emptyMap();
+        }
+        
         HashMap<String, String> newParams = new HashMap<String, String>();
 
         String trimmedKeyName;
@@ -151,7 +155,7 @@ public class ExternalAuthnSystemLoginHandler extends AbstractLoginHandler {
 
         // forward control to the servlet.
         try {
-            String profileUrl = HttpServletHelper.getContextRelativeUrl(httpRequest, protectedPath).buildURL();
+            String profileUrl = buildRedirectUrl(httpRequest);
 
             log.debug("Redirecting to {}", profileUrl);
             httpResponse.sendRedirect(profileUrl);
index 49bb972..ca393d3 100644 (file)
@@ -21,6 +21,7 @@ import javax.xml.namespace.QName;
 import edu.internet2.middleware.shibboleth.common.config.BaseSpringNamespaceHandler;
 import edu.internet2.middleware.shibboleth.common.config.profile.JSPErrorHandlerBeanDefinitionParser;
 import edu.internet2.middleware.shibboleth.common.config.profile.VelocityErrorHandlerBeanDefinitionParser;
+import edu.internet2.middleware.shibboleth.idp.config.profile.authn.ExternalAuthnSystemLoginHandlerBeanDefinitionParser;
 import edu.internet2.middleware.shibboleth.idp.config.profile.authn.IPAddressLoginHandlerBeanDefinitionParser;
 import edu.internet2.middleware.shibboleth.idp.config.profile.authn.PreviousSessionLoginHandlerBeanDefinitionParser;
 import edu.internet2.middleware.shibboleth.idp.config.profile.authn.RemoteUserLoginHandlerBeanDefinitionParser;
@@ -87,6 +88,9 @@ public class ProfileHandlerNamespaceHandler extends BaseSpringNamespaceHandler {
 
         registerBeanDefinitionParser(RemoteUserLoginHandlerBeanDefinitionParser.SCHEMA_TYPE,
                 new RemoteUserLoginHandlerBeanDefinitionParser());
+        
+        registerBeanDefinitionParser(ExternalAuthnSystemLoginHandlerBeanDefinitionParser.SCHEMA_TYPE,
+                new ExternalAuthnSystemLoginHandlerBeanDefinitionParser());
 
         registerBeanDefinitionParser(UsernamePasswordLoginHandlerBeanDefinitionParser.SCHEMA_TYPE,
                 new UsernamePasswordLoginHandlerBeanDefinitionParser());
diff --git a/src/main/java/edu/internet2/middleware/shibboleth/idp/config/profile/authn/ExternalAuthnSystemLoginHandlerBeanDefinitionParser.java b/src/main/java/edu/internet2/middleware/shibboleth/idp/config/profile/authn/ExternalAuthnSystemLoginHandlerBeanDefinitionParser.java
new file mode 100644 (file)
index 0000000..b01af27
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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.authn;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.opensaml.xml.util.DatatypeHelper;
+import org.opensaml.xml.util.XMLHelper;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.w3c.dom.Element;
+
+import edu.internet2.middleware.shibboleth.idp.config.profile.ProfileHandlerNamespaceHandler;
+
+/**
+ * Spring bean definition parser for remote user authentication handlers.
+ */
+public class ExternalAuthnSystemLoginHandlerBeanDefinitionParser extends AbstractLoginHandlerBeanDefinitionParser {
+
+    /** Schema type. */
+    public static final QName SCHEMA_TYPE = new QName(ProfileHandlerNamespaceHandler.NAMESPACE, "ExternalAuthn");
+
+    /** {@inheritDoc} */
+    protected Class getBeanClass(Element arg0) {
+        return ExternalAuthnSystemLoginHandlerFactoryBean.class;
+    }
+
+    /** {@inheritDoc} */
+    protected void doParse(Element config, BeanDefinitionBuilder builder) {
+        super.doParse(config, builder);
+
+        if (config.hasAttributeNS(null, "protectedServletPath")) {
+            builder.addPropertyValue("protectedServletPath",
+                    DatatypeHelper.safeTrimOrNullString(config.getAttributeNS(null, "protectedServletPath")));
+        } else {
+            builder.addPropertyValue("protectedServletPath", "/Authn/External");
+        }
+
+        List<Element> queryParamElements = XMLHelper.getChildElementsByTagNameNS(config,
+                ProfileHandlerNamespaceHandler.NAMESPACE, "QueryParam");
+        builder.addPropertyValue("queryParams", parseQueryParameters(queryParamElements));
+    }
+
+    /**
+     * Parses the query parameter elements, if any, in to a map.
+     * 
+     * @param queryParamElements query parameter elements, may be null or empty
+     * 
+     * @return the map of query elements indexed by the parameter name
+     */
+    protected Map<String, String> parseQueryParameters(List<Element> queryParamElements) {
+        if (queryParamElements == null || queryParamElements.isEmpty()) {
+            return Collections.emptyMap();
+        }
+
+        HashMap<String, String> params = new HashMap<String, String>();
+
+        String paramName;
+        String paramValue;
+        for (Element queryParamElement : queryParamElements) {
+            paramName = DatatypeHelper.safeTrimOrNullString(queryParamElement.getAttributeNS(null, "name"));
+            if (paramName == null) {
+                throw new BeanCreationException("Query parameter name may not be null or empty");
+            }
+            paramValue = DatatypeHelper.safeTrimOrNullString(queryParamElement.getAttributeNS(null, "value"));
+            if (paramValue == null) {
+                throw new BeanCreationException("Query parameter value may not be null or empty");
+            }
+            params.put(paramName, paramValue);
+        }
+
+        return params;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/edu/internet2/middleware/shibboleth/idp/config/profile/authn/ExternalAuthnSystemLoginHandlerFactoryBean.java b/src/main/java/edu/internet2/middleware/shibboleth/idp/config/profile/authn/ExternalAuthnSystemLoginHandlerFactoryBean.java
new file mode 100644 (file)
index 0000000..2fb011d
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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.authn;
+
+import java.util.Map;
+
+import edu.internet2.middleware.shibboleth.idp.authn.provider.ExternalAuthnSystemLoginHandler;
+
+/**
+ * Spring factory for {@link ExternalAuthnSystemLoginHandler}.
+ */
+public class ExternalAuthnSystemLoginHandlerFactoryBean extends AbstractLoginHandlerFactoryBean {
+
+    /** Path to protected servlet. */
+    private String protectedServletPath;
+
+    /** Static query parameters added to the request to the external authentication system invocation. */
+    private Map<String, String> queryParams;
+
+    /** {@inheritDoc} */
+    public Class getObjectType() {
+        return ExternalAuthnSystemLoginHandler.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 path to protected servlet
+     */
+    public void setProtectedServletPath(String path) {
+        protectedServletPath = path;
+    }
+
+    /**
+     * Gets the static query parameters added to the request to the external authentication system invocation.
+     * 
+     * @return static query parameters added to the request to the external authentication system invocation
+     */
+    public Map<String, String> getQueryParams() {
+        return queryParams;
+    }
+
+    /**
+     * Sets the static query parameters added to the request to the external authentication system invocation.
+     * 
+     * @param params static query parameters added to the request to the external authentication system invocation
+     */
+    public void setQueryParams(Map<String, String> params) {
+        queryParams = params;
+    }
+
+    /** {@inheritDoc} */
+    protected Object createInstance() throws Exception {
+        ExternalAuthnSystemLoginHandler handler = new ExternalAuthnSystemLoginHandler();
+        handler.setProtectedPath(getProtectedServletPath());
+        handler.setQueryParameters(queryParams);
+        populateHandler(handler);
+        return handler;
+    }
+}
\ No newline at end of file
index ba2cdc6..a56b507 100644 (file)
@@ -663,11 +663,12 @@ public abstract class AbstractSAMLProfileHandler extends
      */
     protected <T extends SAMLNameIdentifierEncoder> Pair<BaseAttribute, T> selectNameIDAttributeAndEncoder(
             Collection<BaseAttribute<?>> attributes, Class<T> nameIdEncoderType, String[] formatPrecedence) {
-        log.debug("Selecting attribute to be encoded as a name identifier by encoder of type {}",
-                nameIdEncoderType.getName());
         if (attributes.isEmpty()) {
             return null;
         }
+        
+        log.debug("Selecting attribute to be encoded as a name identifier by encoder of type {}",
+                nameIdEncoderType.getName());
 
         T nameIdEncoder;
 
index 0d370ee..b30cd6b 100644 (file)
             </xsd:extension>
         </xsd:complexContent>
     </xsd:complexType>
+    
+    <xsd:complexType name="ExternalAuthn">
+        <xsd:complexContent>
+            <xsd:extension base="LoginHandlerType">
+                <xsd:sequence>
+                    <xsd:element name="QueryParam" minOccurs="0" maxOccurs="unbounded">
+                        <xsd:complexType>
+                            <xsd:attribute name="name" type="xsd:string" use="required" />
+                            <xsd:attribute name="value" type="xsd:string" use="required" />
+                        </xsd:complexType>                    
+                    </xsd:element>
+                </xsd:sequence>
+                <xsd:attribute name="protectedServletPath" type="xsd:string">
+                    <xsd:annotation>
+                        <xsd:documentation>
+                            The servlet context path to the
+                            edu.internet2.middleware.shibboleth.idp.authn.provider.ExternalAuthnSystemServlet instance
+                            protected by an external authentication system that is integrated with the web server, Servlet
+                            container, or IdP.
+                        </xsd:documentation>
+                    </xsd:annotation>
+                </xsd:attribute>
+            </xsd:extension>
+        </xsd:complexContent>
+    </xsd:complexType>
 
     <xsd:complexType name="RemoteUser">
         <xsd:complexContent>
index fa69565..cf12a11 100644 (file)
@@ -1,27 +1,32 @@
-<?xml version="1.0" encoding="ISO-8859-1" ?>\r
-<!DOCTYPE taglib\r\r
-        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"\r
-        "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">\r
-<taglib>\r
-  <tlibversion>1.0</tlibversion>\r
-  <jspversion>1.2</jspversion>\r
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"\r
+    version="2.0">\r
+    \r
+  <tlib-version>1.0</tlib-version>\r
+  <short-name>mdui</short-name>\r
+  <uri>urn:mace:shibboleth:2.0:idp:mdui</uri>\r
+  \r
   <tag>\r
+    <description>Service Name - some user friendly descriptionrmation about the relying party</description>\r
     <name>serviceName</name>\r
-    <tagclass>edu.internet2.middleware.shibboleth.idp.ui.ServiceNameTag</tagclass>\r
-    <bodycontent>empty</bodycontent>\r
-    <info>Service Name - some user friendly information about the relying party</info>\r
+    <tag-class>edu.internet2.middleware.shibboleth.idp.ui.ServiceNameTag</tag-class>\r
+    <body-content>empty</body-content>\r
+    \r
   </tag>\r
+  \r
   <tag>\r
+    <description>Service Description - taken from the mdui statement</description>\r
     <name>serviceDescription</name>\r
-    <tagclass>edu.internet2.middleware.shibboleth.idp.ui.ServiceDescriptionTag</tagclass>\r
-    <bodycontent>scriptless</bodycontent>\r
-    <info>Service Description - taken from the mdui statement</info>\r
+    <tag-class>edu.internet2.middleware.shibboleth.idp.ui.ServiceDescriptionTag</tag-class>\r
+    <body-content>scriptless</body-content>\r
   </tag>\r
+  \r
   <tag>\r
+    <description>Service Contact - descriptionrmation about contact description on the SP</description>\r
     <name>serviceContact</name>\r
-    <tagclass>edu.internet2.middleware.shibboleth.idp.ui.ServiceContactTag</tagclass>\r
-    <bodycontent>scriptless</bodycontent>\r
-    <info>Service Contact - information about contact info on the SP</info>\r
+    <tag-class>edu.internet2.middleware.shibboleth.idp.ui.ServiceContactTag</tag-class>\r
+    <body-content>scriptless</body-content>\r
     <attribute>\r
       <name>contactType</name>\r
       <required>false</required>\r
       <rtexprvalue>true</rtexprvalue>\r
     </attribute>\r
   </tag>\r
+  \r
   <tag>\r
+    <description>Service PrivacyURL - directly from the metadata if present</description>\r
     <name>servicePrivacyURL</name>\r
-    <tagclass>edu.internet2.middleware.shibboleth.idp.ui.ServicePrivacyURLTag</tagclass>\r
-    <bodycontent>scriptless</bodycontent>\r
-    <info>Service PrivacyURL - directly from the metadata if present</info>\r
+    <tag-class>edu.internet2.middleware.shibboleth.idp.ui.ServicePrivacyURLTag</tag-class>\r
+    <body-content>scriptless</body-content>\r
     <attribute>\r
       <name>linkText</name>\r
       <required>true</required>\r
       <rtexprvalue>true</rtexprvalue>\r
     </attribute>\r
   </tag>\r
+  \r
   <tag>\r
-    <name>serviceInformationURL</name>\r
-    <tagclass>edu.internet2.middleware.shibboleth.idp.ui.ServiceInformationURLTag</tagclass>\r
-    <bodycontent>scriptless</bodycontent>\r
-    <info>Service InformationURL - directly from the metadata if present</info>\r
+    <description>Service descriptionrmationURL - directly from the metadata if present</description>\r
+    <name>servicedescriptionrmationURL</name>\r
+    <tag-class>edu.internet2.middleware.shibboleth.idp.ui.ServicedescriptionrmationURLTag</tag-class>\r
+    <body-content>scriptless</body-content>\r
     <attribute>\r
       <name>linkText</name>\r
       <required>true</required>\r
       <rtexprvalue>true</rtexprvalue>\r
     </attribute>\r
   </tag>\r
+  \r
   <tag>\r
+    <description>Logo for the SP</description>\r
     <name>serviceLogo</name>\r
-    <tagclass>edu.internet2.middleware.shibboleth.idp.ui.ServiceLogoTag</tagclass>\r
-    <bodycontent>scriptless</bodycontent>\r
-    <info>Logo for the SP</info>\r
+    <tag-class>edu.internet2.middleware.shibboleth.idp.ui.ServiceLogoTag</tag-class>\r
+    <body-content>scriptless</body-content>\r
     <attribute>\r
       <name>minHeight</name>\r
       <required>false</required>\r
       <rtexprvalue>true</rtexprvalue>\r
     </attribute>\r
   </tag>\r
-</taglib>\r
+  \r
+</taglib>
\ No newline at end of file
index 57278b9..89de743 100644 (file)
     <!-- <login-config> <auth-method>FORM</auth-method> <realm-name>IdP Password Authentication</realm-name> <form-login-config> 
         <form-login-page>/login.jsp</form-login-page> <form-error-page>/login-error.jsp</form-error-page> </form-login-config> </login-config> -->
 
-    <taglib>
-      <taglib-uri>/mdui</taglib-uri>
-      <taglib-location>/WEB-INF/mduitaglib.tld</taglib-location>
-    </taglib>
-</web-app>
+</web-app>
\ No newline at end of file
index cd46312..45c9fa9 100644 (file)
@@ -1,5 +1,5 @@
 <%@page import="edu.internet2.middleware.shibboleth.common.profile.AbstractErrorHandler"%>
-<%@ taglib uri="/mdui" prefix="mdui" %>
+<%@ taglib uri="urn:mace:shibboleth:2.0:idp:mdui" prefix="mdui" %>
 
 <html>
 <body>
index 91b1100..8eb4c81 100644 (file)
@@ -1,4 +1,4 @@
-<%@ taglib uri="/mdui" prefix="mdui" %>\r
+<%@ taglib uri="urn:mace:shibboleth:2.0:idp:mdui" prefix="mdui" %>\r
 <html>\r
   <link rel="stylesheet" type="text/css" href="<%= request.getContextPath()%>/login.css"/>\r
   <head>\r