package edu.internet2.middleware.shibboleth.idp.profile.saml1;
import org.apache.log4j.Logger;
+import org.joda.time.DateTime;
+import org.joda.time.chrono.ISOChronology;
import org.opensaml.common.binding.decoding.SAMLMessageDecoder;
import org.opensaml.saml1.binding.decoding.BaseSAML1MessageDecoder;
import org.opensaml.ws.message.MessageContext;
throw new MessageDecodingException(
"No providerId parameter given in Shibboleth SSO authentication request.");
}
- requestContext.setPeerEntityId(providerId);
+ requestContext.setInboundMessageIssuer(providerId);
String shire = DatatypeHelper.safeTrimOrNullString(transport.getParameterValue("shire"));
if (shire == null) {
String timeStr = DatatypeHelper.safeTrimOrNullString(transport.getParameterValue("time"));
if (timeStr != null) {
long time = Long.parseLong(timeStr);
- requestContext.setTime(time);
+ requestContext.setInboundSAMLMessageIssueInstant(new DateTime(time, ISOChronology.getInstanceUTC()));
}
- populateMessageContext(requestContext);
+ populateRelyingPartyMetadata(requestContext);
}
}
\ No newline at end of file
import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfiguration;
import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml1.ShibbolethSSOConfiguration;
-import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml2.SSOConfiguration;
import edu.internet2.middleware.shibboleth.common.util.HttpHelper;
import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
import edu.internet2.middleware.shibboleth.idp.authn.ShibbolethSSOLoginContext;
ShibbolethSSORequestContext requestContext = decodeRequest(inTransport, outTransport);
ShibbolethSSOLoginContext loginContext = requestContext.getLoginContext();
- if (getRelyingPartyConfiguration(loginContext.getRelyingPartyId()) == null) {
+ RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(loginContext.getRelyingPartyId());
+ ShibbolethSSOConfiguration ssoConfig = (ShibbolethSSOConfiguration) rpConfig.getProfileConfigurations().get(ShibbolethSSOConfiguration.PROFILE_ID);
+ if (ssoConfig == null) {
log.error("Shibboleth SSO profile is not configured for relying party " + loginContext.getRelyingPartyId());
throw new ProfileException("Shibboleth SSO profile is not configured for relying party "
+ loginContext.getRelyingPartyId());
}
ShibbolethSSOLoginContext loginContext = new ShibbolethSSOLoginContext();
- loginContext.setRelyingParty(requestContext.getPeerEntityId());
+ loginContext.setRelyingParty(requestContext.getInboundMessageIssuer());
loginContext.setSpAssertionConsumerService(requestContext.getSpAssertionConsumerService());
loginContext.setSpTarget(requestContext.getRelayState());
loginContext.setAuthenticationEngineURL(authenticationManagerPath);
ShibbolethSSORequestContext requestContext = new ShibbolethSSORequestContext();
try {
+ requestContext.setMessageDecoder(getMessageDecoders().get(getInboundBinding()));
+
requestContext.setLoginContext(loginContext);
requestContext.setPrincipalName(loginContext.getPrincipalName());
requestContext.setPrincipalAuthenticationMethod(loginContext.getAuthenticationMethod());
requestContext.setMetadataProvider(metadataProvider);
String relyingPartyId = loginContext.getRelyingPartyId();
- requestContext.setPeerEntityId(relyingPartyId);
+ requestContext.setInboundMessageIssuer(relyingPartyId);
EntityDescriptor relyingPartyMetadata = metadataProvider.getEntityDescriptor(relyingPartyId);
requestContext.setPeerEntityMetadata(relyingPartyMetadata);
requestContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
public class ShibbolethSSORequestContext extends
BaseSAML1ProfileRequestContext<Request, Response, ShibbolethSSOConfiguration> {
- /** Time since the epoch. */
- private long time;
-
/** SP-provide assertion consumer service URL. */
private String spAssertionConsumerService;
public void setSpAssertionConsumerService(String acs) {
spAssertionConsumerService = acs;
}
-
- /**
- * Sets the time since the epoch.
- *
- * @return time since the epoch
- */
- public long getTime() {
- return time;
- }
-
- /**
- * Sets the time since the epoch.
- *
- * @param time time since the epoch
- */
- public void setTime(long time) {
- this.time = time;
- }
}
}
\ No newline at end of file
try {
SSORequestContext requestContext = decodeRequest(inTransport, outTransport);
- String relyingPartyId = requestContext.getPeerEntityId();
+ String relyingPartyId = requestContext.getInboundMessageIssuer();
RelyingPartyConfiguration rpConfig = getRelyingPartyConfiguration(relyingPartyId);
if (rpConfig == null) {
log.error("No relying party configuration for " + relyingPartyId);
requestContext.setMetadataProvider(metadataProvider);
String relyingPartyId = loginContext.getRelyingPartyId();
- requestContext.setPeerEntityId(relyingPartyId);
+ requestContext.setInboundMessageIssuer(relyingPartyId);
EntityDescriptor relyingPartyMetadata = metadataProvider.getEntityDescriptor(relyingPartyId);
requestContext.setPeerEntityMetadata(relyingPartyMetadata);
requestContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
<!-- ========================================== -->
<!-- Relying Party Configurations -->
<!-- ========================================== -->
- <!--
<AnonymousRelyingParty provider="http://example.org/IdP" />
<DefaultRelyingParty provider="http://example.org/IdP" />
- -->
- <RelyingParty id="urn:example.org:myFederation"
- provider="urn:example.org:myFederation:idp1">
+ <RelyingParty id="urn:example.org"
+ provider="urn:example.org:idp1">
<ProfileConfiguration xsi:type="saml:ShibbolethSSOProfile" />
- <!--
<ProfileConfiguration xsi:type="saml:SAML1AttributeQueryProfile" />
<ProfileConfiguration xsi:type="saml:SAML2SSOProfile" />
<ProfileConfiguration xsi:type="saml:SAML2AttributeQueryProfile" />
- -->
</RelyingParty>
+ <RelyingParty id="urn:example.org:BogusSP"
+ provider="urn:example.org:idp1" />
+
<!-- ========================================== -->
<!-- Metadata Configuration -->
<!-- ========================================== -->
-
- <!-- MetadataProvider reading metadata from a URL. -->
- <!-- Fill in metadataURL and backingFile attributes with deployment specific information -->
- <!--
- <MetadataProvider id="URLMD" xsi:type="FileBackedHTTPMetadataProvider" xmlns="urn:mace:shibboleth:2.0:metadata"
- metadataURL="http://example.org/my/metadata/file.xml" backingFile="$IDP_HOME$/temp/metadata/somefile.xml" />
- -->
-
- <!-- MetadataProvider reading metadata from the filesystem -->
- <!-- Fill in metadataFile attribute with deployment specific information -->
- <!--
- <MetadataProvider id="FSMD" xsi:type="FilesystemMetadataProvider" xmlns="urn:mace:shibboleth:2.0:metadata"
- metadataFile="$IDP_HOME$/metadata/somefile.xml" />
- -->
-
- <!-- MetadataProvider defining metadata inline -->
- <!--
<MetadataProvider id="InlineMD" xsi:type="InlineMetadataProvider" xmlns="urn:mace:shibboleth:2.0:metadata">
- <EntitiesDescriptor Name="urn:example.org:myFederation" xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
- <EntityDescriptor entityID="urn:example.org:myFederation:idp1">
- <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+
+ <EntitiesDescriptor Name="urn:example.org" xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
+
+ <EntityDescriptor entityID="urn:example.org:idp1">
+ <IDPSSODescriptor protocolSupportEnumeration="urn:mace:shibboleth:1.0 urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol">
+ <NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
+ <SingleSignOnService Binding="urn:mace:shibboleth:1.0:profiles:AuthnRequest" Location="https://example.org/myIdP"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://example.org/myIdP" />
</IDPSSODescriptor>
</EntityDescriptor>
- <EntityDescriptor entityID="urn:example.org:myFederation:sp1">
- <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+
+ <EntityDescriptor entityID="urn:example.org:sp1">
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol">
+ <NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location="https://example.org/mySP" index="0"/>
<AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://example.org/mySP" index="0" />
<AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://example.org/mySP" index="0" />
</SPSSODescriptor>
</EntityDescriptor>
+
</EntitiesDescriptor>
+
</MetadataProvider>
- -->
-
- <!-- MetadataProvider the combining other MetadataProviders -->
- <!--
- <MetadataProvider id="ExampleMD" xsi:type="ChainingMetadataProvider" xmlns="urn:mace:shibboleth:2.0:metadata">
- <MetadataProvider id="URLMD" xsi:type="FileBackedHTTPMetadataProvider"
- metadataURL="http://example.org/my/metadata" backingFile="/path/to/temp/location" />
- <MetadataProvider id="FSMD" xsi:type="FilesystemMetadataProvider" metadataFile="/path/to/metadata/file.xml" />
- </MetadataProvider>
- -->
<!-- ========================================== -->
<!-- Security Configurations -->
<!-- ========================================== -->
<security:SecurityPolicy id="shibboleth.DefaultSecurityPolicy" xsi:type="security:SecurityPolicyType">
- <security:Rule xsi:type="samlsec:SAML1Protocol"/>
- <security:Rule xsi:type="samlsec:SAML2Protocol"/>
<security:Rule xsi:type="samlsec:Replay"/>
<security:Rule xsi:type="samlsec:IssueInstant"/>
<security:Rule xsi:type="samlsec:MandatoryIssuer"/>
String authnRequestString = getSamlRequestString(authnRequest);
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
- servletRequest.setPathInfo("/IdP/saml2/SSONoAuth");
+ servletRequest.setPathInfo("/saml2/POST/SSO");
servletRequest.setParameter("SAMLRequest", Base64.encodeBytes(authnRequestString.getBytes()));
MockHttpServletResponse servletResponse = new MockHttpServletResponse();
String authnRequestString = getSamlRequestString(authnRequest);
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
- servletRequest.setPathInfo("/IdP/saml2/SSONoAuth");
+ servletRequest.setPathInfo("/saml2/POST/SSO");
servletRequest.setParameter("SAMLRequest", Base64.encodeBytes(authnRequestString.getBytes()));
MockHttpServletResponse servletResponse = new MockHttpServletResponse();
loginContext.setPrincipalName("testUser");
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
- servletRequest.setPathInfo("/IdP/saml2/SSONoAuth");
+ servletRequest.setPathInfo("/saml2/POST/SSO");
HttpSession session = servletRequest.getSession();
session.setAttribute(Saml2LoginContext.LOGIN_CONTEXT_KEY, loginContext);
--- /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.system.conf1;
+
+import javax.servlet.http.HttpSession;
+
+import org.joda.time.DateTime;
+import org.opensaml.ws.transport.http.HTTPInTransport;
+import org.opensaml.ws.transport.http.HTTPOutTransport;
+import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
+import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
+import edu.internet2.middleware.shibboleth.common.profile.ProfileHandler;
+import edu.internet2.middleware.shibboleth.common.profile.ProfileHandlerManager;
+import edu.internet2.middleware.shibboleth.idp.authn.ShibbolethSSOLoginContext;
+
+/**
+ * Unit test for Shibboleth SSO requests.
+ */
+public class ShibbolethSSOTestCase extends BaseConf1TestCase {
+
+ /** Tests initial leg of the SSO request where request is decoded and sent to the authentication engine. */
+ public void testFirstAuthenticationLeg() throws Exception {
+ MockHttpServletRequest servletRequest = buildServletRequest();
+ MockHttpServletResponse servletResponse = new MockHttpServletResponse();
+
+ ProfileHandlerManager handlerManager = (ProfileHandlerManager) getApplicationContext().getBean(
+ "shibboleth.HandlerManager");
+ ProfileHandler handler = handlerManager.getProfileHandler(servletRequest);
+ assertNotNull(handler);
+
+ // Process request
+ HTTPInTransport profileRequest = new HttpServletRequestAdapter(servletRequest);
+ HTTPOutTransport profileResponse = new HttpServletResponseAdapter(servletResponse);
+ handler.processRequest(profileRequest, profileResponse);
+
+ HttpSession session = servletRequest.getSession();
+ ShibbolethSSOLoginContext loginContext = (ShibbolethSSOLoginContext) session
+ .getAttribute(ShibbolethSSOLoginContext.LOGIN_CONTEXT_KEY);
+
+ assertNotNull(loginContext);
+ assertEquals(false, loginContext.getAuthenticationAttempted());
+ assertEquals(false, loginContext.getForceAuth());
+ assertEquals(false, loginContext.getPassiveAuth());
+ assertEquals("/AuthnEngine", loginContext.getAuthenticationEngineURL());
+ assertEquals("/shibboleth/SSO", loginContext.getProfileHandlerURL());
+ assertEquals("urn:example.org:sp", loginContext.getRelyingPartyId());
+ assertEquals(0, loginContext.getRequestedAuthenticationMethods().size());
+ assertEquals("https://example.org/mySP", loginContext.getSpAssertionConsumerService());
+ assertEquals("https://example.org/mySP", loginContext.getSpTarget());
+
+ assertEquals("/AuthnEngine", servletResponse.getForwardedUrl());
+ }
+
+ /** Tests second leg of the SSO request where request returns to SSO handler and AuthN statement is generated. */
+ public void testSecondAuthenticationLeg() throws Exception {
+ MockHttpServletRequest servletRequest = buildServletRequest();
+ MockHttpServletResponse servletResponse = new MockHttpServletResponse();
+
+ HttpSession httpSession = servletRequest.getSession(true);
+ httpSession.setAttribute(ShibbolethSSOLoginContext.LOGIN_CONTEXT_KEY, buildLoginContext());
+
+ ProfileHandlerManager handlerManager = (ProfileHandlerManager) getApplicationContext().getBean(
+ "shibboleth.HandlerManager");
+ ProfileHandler handler = handlerManager.getProfileHandler(servletRequest);
+ assertNotNull(handler);
+
+ // Process request
+ HTTPInTransport profileRequest = new HttpServletRequestAdapter(servletRequest);
+ HTTPOutTransport profileResponse = new HttpServletResponseAdapter(servletResponse);
+ handler.processRequest(profileRequest, profileResponse);
+
+ String response = servletResponse.getContentAsString();
+ assertTrue(response.contains("action=\"https://example.org/mySP\" method=\"post\""));
+ assertTrue(response.contains("name=\"TARGET\" value=\"https://example.org/mySP\""));
+ assertTrue(response.contains("SAMLResponse"));
+ }
+
+ /** Tests that the SSO handler correctly fails out if the Shib SSO profile is not configured. */
+ public void testAuthenticationWithoutConfiguredSSO() {
+ MockHttpServletRequest servletRequest = buildServletRequest();
+ servletRequest.setParameter("providerId", "urn:example.org:BogusSP");
+
+ MockHttpServletResponse servletResponse = new MockHttpServletResponse();
+
+ ProfileHandlerManager handlerManager = (ProfileHandlerManager) getApplicationContext().getBean(
+ "shibboleth.HandlerManager");
+ ProfileHandler handler = handlerManager.getProfileHandler(servletRequest);
+ assertNotNull(handler);
+
+ // Process request
+ HTTPInTransport profileRequest = new HttpServletRequestAdapter(servletRequest);
+ HTTPOutTransport profileResponse = new HttpServletResponseAdapter(servletResponse);
+ try {
+ handler.processRequest(profileRequest, profileResponse);
+ fail("Request processing expected to due to lack of configured Shib SSO profile");
+ } catch (ProfileException e) {
+
+ }
+ }
+
+ protected MockHttpServletRequest buildServletRequest() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setPathInfo("/shibboleth/SSO");
+ request.setParameter("providerId", "urn:example.org:sp1");
+ request.setParameter("shire", "https://example.org/mySP");
+ request.setParameter("target", "https://example.org/mySP");
+
+ return request;
+ }
+
+ protected ShibbolethSSOLoginContext buildLoginContext() {
+ ShibbolethSSOLoginContext loginContext = new ShibbolethSSOLoginContext();
+ loginContext.setAuthenticationInstant(new DateTime());
+ loginContext.setAuthenticationMethod("urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified");
+ loginContext.setPrincipalAuthenticated(true);
+ loginContext.setPrincipalName("testUser");
+ loginContext.setRelyingParty("urn:example.org:sp1");
+ loginContext.setSpAssertionConsumerService("https://example.org/mySP");
+ loginContext.setSpTarget("https://example.org/mySP");
+
+ return loginContext;
+ }
+}
\ No newline at end of file