Bug fixing - round two... now with working shib SSO
authorlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 19 Jun 2007 20:53:03 +0000 (20:53 +0000)
committerlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 19 Jun 2007 20:53:03 +0000 (20:53 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@2256 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

resources/conf/relying-party.xml
src/edu/internet2/middleware/shibboleth/idp/authn/AuthenticationEngine.java
src/edu/internet2/middleware/shibboleth/idp/authn/provider/RemoteUserAuthenticationHandler.java
src/edu/internet2/middleware/shibboleth/idp/profile/saml1/ShibbolethSSOProfileHandler.java
src/edu/internet2/middleware/shibboleth/idp/profile/saml2/SSOProfileHandler.java
src/edu/internet2/middleware/shibboleth/idp/util/HttpHelper.java [new file with mode: 0644]

index f0b0660..218fb3f 100644 (file)
     <DefaultRelyingParty provider="http://example.org/IdP" />
     
     <RelyingParty id="urn:example.org:unitTestFed"
     <DefaultRelyingParty provider="http://example.org/IdP" />
     
     <RelyingParty id="urn:example.org:unitTestFed"
-                  provider="http://example.org/IdP">
+                  provider="urn:example.org:unitTest:idp1">
         <ProfileConfiguration xsi:type="saml:SAML2AttributeQueryProfile" />
         <ProfileConfiguration xsi:type="saml:SAML2SSOProfile" />
     </RelyingParty>
     
     <MetadataProvider id="UnitTestConf1" xsi:type="InlineMetadataProvider" xmlns="urn:mace:shibboleth:2.0:metadata">
         <EntitiesDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
         <ProfileConfiguration xsi:type="saml:SAML2AttributeQueryProfile" />
         <ProfileConfiguration xsi:type="saml:SAML2SSOProfile" />
     </RelyingParty>
     
     <MetadataProvider id="UnitTestConf1" xsi:type="InlineMetadataProvider" xmlns="urn:mace:shibboleth:2.0:metadata">
         <EntitiesDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
+            <EntityDescriptor entityID="urn:example.org:unitTest:idp1">
+                <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+                    <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://example.org/myIdP" />
+                </IDPSSODescriptor>
+            </EntityDescriptor>
             <EntityDescriptor entityID="urn:example.org:unitTest:sp1">
                 <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
                     <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://example.org/mySP" index="0" />
             <EntityDescriptor entityID="urn:example.org:unitTest:sp1">
                 <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
                     <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://example.org/mySP" index="0" />
index f921dfa..a0f7c48 100644 (file)
@@ -40,6 +40,7 @@ import edu.internet2.middleware.shibboleth.idp.session.ServiceInformation;
 import edu.internet2.middleware.shibboleth.idp.session.Session;
 import edu.internet2.middleware.shibboleth.idp.session.impl.AuthenticationMethodInformationImpl;
 import edu.internet2.middleware.shibboleth.idp.session.impl.ServiceInformationImpl;
 import edu.internet2.middleware.shibboleth.idp.session.Session;
 import edu.internet2.middleware.shibboleth.idp.session.impl.AuthenticationMethodInformationImpl;
 import edu.internet2.middleware.shibboleth.idp.session.impl.ServiceInformationImpl;
+import edu.internet2.middleware.shibboleth.idp.util.HttpHelper;
 
 /**
  * Manager responsible for handling authentication requests.
 
 /**
  * Manager responsible for handling authentication requests.
@@ -113,6 +114,7 @@ public class AuthenticationEngine extends HttpServlet {
         try {
             RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(forwardPath);
             dispatcher.forward(httpRequest, httpResponse);
         try {
             RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(forwardPath);
             dispatcher.forward(httpRequest, httpResponse);
+            return;
         } catch (IOException e) {
             LOG.fatal("Unable to return control back to authentication engine", e);
         } catch (ServletException e) {
         } catch (IOException e) {
             LOG.fatal("Unable to return control back to authentication engine", e);
         } catch (ServletException e) {
@@ -127,6 +129,10 @@ public class AuthenticationEngine extends HttpServlet {
         if (LOG.isDebugEnabled()) {
             LOG.debug("Processing incoming request");
         }
         if (LOG.isDebugEnabled()) {
             LOG.debug("Processing incoming request");
         }
+        
+        if(httpResponse.isCommitted()){
+            LOG.error("HTTP Response already committed");
+        }
 
         HttpSession httpSession = httpRequest.getSession();
         LoginContext loginContext = (LoginContext) httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
 
         HttpSession httpSession = httpRequest.getSession();
         LoginContext loginContext = (LoginContext) httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
@@ -163,6 +169,8 @@ public class AuthenticationEngine extends HttpServlet {
             }
             authenticateUserWithoutActiveMethod2(httpRequest, httpResponse);
         }
             }
             authenticateUserWithoutActiveMethod2(httpRequest, httpResponse);
         }
+        
+        return;
     }
 
     /**
     }
 
     /**
@@ -222,6 +230,7 @@ public class AuthenticationEngine extends HttpServlet {
             LOG.error("No AuthenticationHandler satisfys the request from relying party: "
                     + loginContext.getRelyingPartyId());
             returnToProfileHandler(loginContext, httpRequest, httpResponse);
             LOG.error("No AuthenticationHandler satisfys the request from relying party: "
                     + loginContext.getRelyingPartyId());
             returnToProfileHandler(loginContext, httpRequest, httpResponse);
+            return;
         }
 
         if (LOG.isDebugEnabled()) {
         }
 
         if (LOG.isDebugEnabled()) {
@@ -230,7 +239,7 @@ public class AuthenticationEngine extends HttpServlet {
         loginContext.setAuthenticationAttempted();
         loginContext.setAuthenticationDuration(handler.getSecond().getAuthenticationDuration());
         loginContext.setAuthenticationMethod(handler.getFirst());
         loginContext.setAuthenticationAttempted();
         loginContext.setAuthenticationDuration(handler.getSecond().getAuthenticationDuration());
         loginContext.setAuthenticationMethod(handler.getFirst());
-        loginContext.setAuthenticationEngineURL(httpRequest.getRequestURI());
+        loginContext.setAuthenticationEngineURL(HttpHelper.getRequestUriWithoutContext(httpRequest));
 
         if (LOG.isDebugEnabled()) {
             LOG.debug("Transferring control to authentication handler of type: "
 
         if (LOG.isDebugEnabled()) {
             LOG.debug("Transferring control to authentication handler of type: "
@@ -260,6 +269,7 @@ public class AuthenticationEngine extends HttpServlet {
             LOG.error("No principal name returned from authentication method: "
                     + loginContext.getAuthenticationMethod());
             returnToProfileHandler(loginContext, httpRequest, httpResponse);
             LOG.error("No principal name returned from authentication method: "
                     + loginContext.getAuthenticationMethod());
             returnToProfileHandler(loginContext, httpRequest, httpResponse);
+            return;
         }
         loginContext.setPrincipalName(principalName);
 
         }
         loginContext.setPrincipalName(principalName);
 
index b2631d1..aa63622 100644 (file)
@@ -61,6 +61,7 @@ public class RemoteUserAuthenticationHandler extends AbstractAuthenticationHandl
         try {
             RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(servletURL);
             dispatcher.forward(httpRequest, httpResponse);
         try {
             RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(servletURL);
             dispatcher.forward(httpRequest, httpResponse);
+            return;
         } catch (IOException ex) {
             log.error("RemoteUserAuthenticationHandler: Unable to forward control to SSO servlet.", ex);
         } catch (ServletException ex) {
         } catch (IOException ex) {
             log.error("RemoteUserAuthenticationHandler: Unable to forward control to SSO servlet.", ex);
         } catch (ServletException ex) {
index 87e1e74..3cceeca 100644 (file)
@@ -32,14 +32,18 @@ import javax.servlet.http.HttpSession;
 import org.apache.log4j.Logger;
 import org.opensaml.common.SAMLObject;
 import org.opensaml.common.SAMLObjectBuilder;
 import org.apache.log4j.Logger;
 import org.opensaml.common.SAMLObject;
 import org.opensaml.common.SAMLObjectBuilder;
+import org.opensaml.common.binding.BasicEndpointSelector;
 import org.opensaml.common.binding.BindingException;
 import org.opensaml.common.binding.encoding.MessageEncoder;
 import org.opensaml.common.xml.SAMLConstants;
 import org.opensaml.common.binding.BindingException;
 import org.opensaml.common.binding.encoding.MessageEncoder;
 import org.opensaml.common.xml.SAMLConstants;
+import org.opensaml.log.XMLObjectRenderer;
 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.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.AssertionConsumerService;
+import org.opensaml.saml2.metadata.Endpoint;
 import org.opensaml.saml2.metadata.provider.MetadataProviderException;
 import org.opensaml.xml.util.DatatypeHelper;
 
 import org.opensaml.saml2.metadata.provider.MetadataProviderException;
 import org.opensaml.xml.util.DatatypeHelper;
 
@@ -50,6 +54,7 @@ import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfi
 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;
 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;
+import edu.internet2.middleware.shibboleth.idp.util.HttpHelper;
 
 /** Shibboleth SSO request profile handler. */
 public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
 
 /** Shibboleth SSO request profile handler. */
 public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
@@ -99,11 +104,24 @@ public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
     /** {@inheritDoc} */
     public void processRequest(ProfileRequest<ServletRequest> request, ProfileResponse<ServletResponse> response)
             throws ProfileException {
     /** {@inheritDoc} */
     public void processRequest(ProfileRequest<ServletRequest> request, ProfileResponse<ServletResponse> response)
             throws ProfileException {
+        
+        if(response.getRawResponse().isCommitted()){
+            log.error("HTTP Response already committed");
+        }
 
 
+        if (log.isDebugEnabled()) {
+            log.debug("Processing incomming request");
+        }
         HttpSession httpSession = ((HttpServletRequest) request.getRawRequest()).getSession(true);
         if (httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY) == null) {
         HttpSession httpSession = ((HttpServletRequest) request.getRawRequest()).getSession(true);
         if (httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY) == null) {
+            if (log.isDebugEnabled()) {
+                log.debug("User session does not contain a login context, processing as first leg of request");
+            }
             performAuthentication(request, response);
         } else {
             performAuthentication(request, response);
         } else {
+            if (log.isDebugEnabled()) {
+                log.debug("User session contains a login context, processing as second leg of request");
+            }
             completeAuthenticationRequest(request, response);
         }
     }
             completeAuthenticationRequest(request, response);
         }
     }
@@ -131,6 +149,7 @@ public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
         try {
             RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(authenticationManagerPath);
             dispatcher.forward(httpRequest, httpResponse);
         try {
             RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(authenticationManagerPath);
             dispatcher.forward(httpRequest, httpResponse);
+            return;
         } 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 (IOException ex) {
             log.error("Error forwarding Shibboleth SSO request to AuthenticationManager", ex);
             throw new ProfileException("Error forwarding Shibboleth SSO request to AuthenticationManager", ex);
@@ -203,9 +222,9 @@ public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
                 throw new ProfileException("No providerId parameter in Shibboleth SSO request");
             }
             loginContext.setRelyingParty(URLDecoder.decode(providerId, "UTF-8"));
                 throw new ProfileException("No providerId parameter in Shibboleth SSO request");
             }
             loginContext.setRelyingParty(URLDecoder.decode(providerId, "UTF-8"));
-            
+
             RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(providerId);
             RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(providerId);
-            if(rpConfig == null){
+            if (rpConfig == null) {
                 log.error("No relying party configuration available for " + providerId);
                 throw new ProfileException("No relying party configuration available for " + providerId);
             }
                 log.error("No relying party configuration available for " + providerId);
                 throw new ProfileException("No relying party configuration available for " + providerId);
             }
@@ -229,7 +248,7 @@ public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
         }
 
         loginContext.setAuthenticationEngineURL(authenticationManagerPath);
         }
 
         loginContext.setAuthenticationEngineURL(authenticationManagerPath);
-        loginContext.setProfileHandlerURL(request.getRequestURI());
+        loginContext.setProfileHandlerURL(HttpHelper.getRequestUriWithoutContext(request));
         return loginContext;
     }
 
         return loginContext;
     }
 
@@ -326,12 +345,27 @@ public class ShibbolethSSOProfileHandler extends AbstractSAML1ProfileHandler {
             log.debug("Encoding response to SAML request from relying party " + requestContext.getRelyingPartyId());
         }
 
             log.debug("Encoding response to SAML request from relying party " + requestContext.getRelyingPartyId());
         }
 
-        
-        //TODO endpoint selection
-        MessageEncoder<ServletResponse> encoder = null;
+        BasicEndpointSelector endpointSelector = new BasicEndpointSelector();
+        endpointSelector.setEndpointType(AssertionConsumerService.DEFAULT_ELEMENT_NAME);
+        endpointSelector.setMetadataProvider(getMetadataProvider());
+        endpointSelector.setRelyingParty(requestContext.getRelyingPartyMetadata());
+        endpointSelector.setRelyingPartyRole(requestContext.getRelyingPartyRoleMetadata());
+        endpointSelector.setSamlRequest(requestContext.getSamlRequest());
+        endpointSelector.getSupportedIssuerBindings().addAll(getMessageEncoderFactory().getEncoderBuilders().keySet());
+        Endpoint relyingPartyEndpoint = endpointSelector.selectEndpoint();
+
+        if (relyingPartyEndpoint == null) {
+            log.error("Unable to determine endpoint, from metadata, for relying party "
+                    + requestContext.getRelyingPartyId() + " acting in SPSSO role");
+            throw new ProfileException("Unable to determine endpoint, from metadata, for relying party "
+                    + requestContext.getRelyingPartyId() + " acting in SPSSO role");
+        }
+
+        MessageEncoder<ServletResponse> encoder = getMessageEncoderFactory().getMessageEncoder(
+                relyingPartyEndpoint.getBinding());
 
         super.populateMessageEncoder(encoder);
 
         super.populateMessageEncoder(encoder);
-        ProfileResponse<ServletResponse> profileResponse = requestContext.getProfileResponse(); 
+        ProfileResponse<ServletResponse> profileResponse = requestContext.getProfileResponse();
         encoder.setResponse(profileResponse.getRawResponse());
         encoder.setSamlMessage(requestContext.getSamlResponse());
         requestContext.setMessageEncoder(encoder);
         encoder.setResponse(profileResponse.getRawResponse());
         encoder.setSamlMessage(requestContext.getSamlResponse());
         requestContext.setMessageEncoder(encoder);
index b9a339f..838df00 100644 (file)
@@ -58,6 +58,7 @@ import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfi
 import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml2.SSOConfiguration;
 import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
 import edu.internet2.middleware.shibboleth.idp.authn.Saml2LoginContext;
 import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml2.SSOConfiguration;
 import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
 import edu.internet2.middleware.shibboleth.idp.authn.Saml2LoginContext;
+import edu.internet2.middleware.shibboleth.idp.util.HttpHelper;
 
 /** SAML 2.0 SSO request profile handler. */
 public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
 
 /** SAML 2.0 SSO request profile handler. */
 public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
@@ -193,7 +194,7 @@ public class SSOProfileHandler extends AbstractSAML2ProfileHandler {
 
             Saml2LoginContext loginContext = new Saml2LoginContext(relyingParty, authnRequest);
             loginContext.setAuthenticationEngineURL(authenticationManagerPath);
 
             Saml2LoginContext loginContext = new Saml2LoginContext(relyingParty, authnRequest);
             loginContext.setAuthenticationEngineURL(authenticationManagerPath);
-            loginContext.setProfileHandlerURL(httpRequest.getRequestURI());
+            loginContext.setProfileHandlerURL(HttpHelper.getRequestUriWithoutContext(httpRequest));
             if (loginContext.getRequestedAuthenticationMethods().size() == 0) {
                 loginContext.getRequestedAuthenticationMethods().add(rpConfig.getDefaultAuthenticationMethod());
             }
             if (loginContext.getRequestedAuthenticationMethods().size() == 0) {
                 loginContext.getRequestedAuthenticationMethods().add(rpConfig.getDefaultAuthenticationMethod());
             }
diff --git a/src/edu/internet2/middleware/shibboleth/idp/util/HttpHelper.java b/src/edu/internet2/middleware/shibboleth/idp/util/HttpHelper.java
new file mode 100644 (file)
index 0000000..912abb1
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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.util;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Helper class for dealing with HTTP related resoruces.
+ */
+public final class HttpHelper {
+    
+    /** Constructor. */
+    private HttpHelper(){
+        
+    }
+
+    /**
+     * Gets the request URI as returned by {@link HttpServletRequest#getRequestURI()} but without the servlet context
+     * path.
+     * 
+     * @param request request to get the URI from
+     * 
+     * @return constructed URI
+     */
+    public static String getRequestUriWithoutContext(HttpServletRequest request) {
+        String servletPath = request.getServletPath();
+
+        if (request.getPathInfo() == null) {
+            return servletPath;
+        } else {
+            return servletPath + request.getPathInfo();
+        }
+    }
+}
\ No newline at end of file