Correctly set "Destination" in AuthNRequest message
Fixes gh-7494 https://github.com/spring-projects/spring-security/issues/7494
This commit is contained in:
parent
69eacac514
commit
9731386de5
|
@ -107,12 +107,7 @@ public class Saml2WebSsoAuthenticationRequestFilter extends OncePerRequestFilter
|
||||||
String localSpEntityId = Saml2Utils.getServiceProviderEntityId(relyingParty, request);
|
String localSpEntityId = Saml2Utils.getServiceProviderEntityId(relyingParty, request);
|
||||||
return new Saml2AuthenticationRequest(
|
return new Saml2AuthenticationRequest(
|
||||||
localSpEntityId,
|
localSpEntityId,
|
||||||
Saml2Utils.resolveUrlTemplate(
|
relyingParty.getIdpWebSsoUrl(),
|
||||||
relyingParty.getAssertionConsumerServiceUrlTemplate(),
|
|
||||||
Saml2Utils.getApplicationUri(request),
|
|
||||||
relyingParty.getRemoteIdpEntityId(),
|
|
||||||
relyingParty.getRegistrationId()
|
|
||||||
),
|
|
||||||
relyingParty.getSigningCredentials()
|
relyingParty.getSigningCredentials()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,21 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.samples;
|
package org.springframework.security.samples;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
|
||||||
import org.springframework.boot.SpringBootConfiguration;
|
import net.shibboleth.utilities.java.support.xml.BasicParserPool;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
|
||||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
|
||||||
import org.springframework.test.util.AssertionErrors;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
|
||||||
import org.springframework.test.web.servlet.ResultActions;
|
|
||||||
import org.springframework.test.web.servlet.ResultMatcher;
|
|
||||||
|
|
||||||
import net.shibboleth.utilities.java.support.xml.SerializeSupport;
|
import net.shibboleth.utilities.java.support.xml.SerializeSupport;
|
||||||
|
import net.shibboleth.utilities.java.support.xml.XMLParserException;
|
||||||
import org.hamcrest.Matcher;
|
import org.hamcrest.Matcher;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -38,8 +27,10 @@ import org.opensaml.core.xml.XMLObject;
|
||||||
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
|
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
|
||||||
import org.opensaml.core.xml.io.MarshallerFactory;
|
import org.opensaml.core.xml.io.MarshallerFactory;
|
||||||
import org.opensaml.core.xml.io.MarshallingException;
|
import org.opensaml.core.xml.io.MarshallingException;
|
||||||
|
import org.opensaml.core.xml.io.UnmarshallingException;
|
||||||
import org.opensaml.saml.common.SignableSAMLObject;
|
import org.opensaml.saml.common.SignableSAMLObject;
|
||||||
import org.opensaml.saml.saml2.core.Assertion;
|
import org.opensaml.saml.saml2.core.Assertion;
|
||||||
|
import org.opensaml.saml.saml2.core.AuthnRequest;
|
||||||
import org.opensaml.saml.saml2.core.EncryptedAssertion;
|
import org.opensaml.saml.saml2.core.EncryptedAssertion;
|
||||||
import org.opensaml.saml.saml2.core.EncryptedID;
|
import org.opensaml.saml.saml2.core.EncryptedID;
|
||||||
import org.opensaml.saml.saml2.core.Response;
|
import org.opensaml.saml.saml2.core.Response;
|
||||||
|
@ -55,9 +46,26 @@ import org.opensaml.xmlsec.SignatureSigningParameters;
|
||||||
import org.opensaml.xmlsec.signature.support.SignatureConstants;
|
import org.opensaml.xmlsec.signature.support.SignatureConstants;
|
||||||
import org.opensaml.xmlsec.signature.support.SignatureException;
|
import org.opensaml.xmlsec.signature.support.SignatureException;
|
||||||
import org.opensaml.xmlsec.signature.support.SignatureSupport;
|
import org.opensaml.xmlsec.signature.support.SignatureSupport;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.SpringBootConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.test.util.AssertionErrors;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.ResultActions;
|
||||||
|
import org.springframework.test.web.servlet.ResultMatcher;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.net.URLDecoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.KeyException;
|
import java.security.KeyException;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
|
@ -78,6 +86,7 @@ import static org.springframework.security.samples.OpenSamlActionTestingSupport.
|
||||||
import static org.springframework.security.samples.OpenSamlActionTestingSupport.buildSubjectConfirmation;
|
import static org.springframework.security.samples.OpenSamlActionTestingSupport.buildSubjectConfirmation;
|
||||||
import static org.springframework.security.samples.OpenSamlActionTestingSupport.buildSubjectConfirmationData;
|
import static org.springframework.security.samples.OpenSamlActionTestingSupport.buildSubjectConfirmationData;
|
||||||
import static org.springframework.security.samples.OpenSamlActionTestingSupport.encryptNameId;
|
import static org.springframework.security.samples.OpenSamlActionTestingSupport.encryptNameId;
|
||||||
|
import static org.springframework.security.samples.OpenSamlActionTestingSupport.inflate;
|
||||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
||||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
|
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
|
||||||
import static org.springframework.security.web.WebAttributes.AUTHENTICATION_EXCEPTION;
|
import static org.springframework.security.web.WebAttributes.AUTHENTICATION_EXCEPTION;
|
||||||
|
@ -131,6 +140,29 @@ public class Saml2LoginIntegrationTests {
|
||||||
.andExpect(header().string("Location", containsString("RelayState=relay%20state%20value%20with%20spaces")));
|
.andExpect(header().string("Location", containsString("RelayState=relay%20state%20value%20with%20spaces")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void authenticateRequestWhenWorkingThenDestinationAttributeIsSet() throws Exception {
|
||||||
|
final String redirectedUrl = mockMvc.perform(get("http://localhost:8080/saml2/authenticate/simplesamlphp"))
|
||||||
|
.andExpect(status().is3xxRedirection())
|
||||||
|
.andReturn()
|
||||||
|
.getResponse()
|
||||||
|
.getRedirectedUrl();
|
||||||
|
MultiValueMap<String, String> parameters =
|
||||||
|
UriComponentsBuilder.fromUriString(redirectedUrl).build(true).getQueryParams();
|
||||||
|
String request = parameters.getFirst("SAMLRequest");
|
||||||
|
AssertionErrors.assertNotNull("SAMLRequest parameter is missing", request);
|
||||||
|
request = URLDecoder.decode(request);
|
||||||
|
request = inflate(OpenSamlActionTestingSupport.decode(request));
|
||||||
|
AuthnRequest authnRequest = (AuthnRequest) fromXml(request);
|
||||||
|
String destination = authnRequest.getDestination();
|
||||||
|
assertEquals(
|
||||||
|
"Destination must match",
|
||||||
|
"https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php",
|
||||||
|
destination
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void authenticateWhenResponseIsSignedThenItSucceeds() throws Exception {
|
public void authenticateWhenResponseIsSignedThenItSucceeds() throws Exception {
|
||||||
Assertion assertion = buildAssertion(USERNAME);
|
Assertion assertion = buildAssertion(USERNAME);
|
||||||
|
@ -330,6 +362,16 @@ public class Saml2LoginIntegrationTests {
|
||||||
return SerializeSupport.nodeToString(element);
|
return SerializeSupport.nodeToString(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private XMLObject fromXml(String xml)
|
||||||
|
throws XMLParserException, UnmarshallingException, ComponentInitializationException {
|
||||||
|
BasicParserPool parserPool = new BasicParserPool();
|
||||||
|
parserPool.initialize();
|
||||||
|
Document document = parserPool.parse(new ByteArrayInputStream(xml.getBytes(UTF_8)));
|
||||||
|
Element element = document.getDocumentElement();
|
||||||
|
return XMLObjectProviderRegistrySupport.getUnmarshallerFactory().getUnmarshaller(element).unmarshall(element);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private X509Certificate decodeCertificate(String source) {
|
private X509Certificate decodeCertificate(String source) {
|
||||||
try {
|
try {
|
||||||
final CertificateFactory factory = CertificateFactory.getInstance("X.509");
|
final CertificateFactory factory = CertificateFactory.getInstance("X.509");
|
||||||
|
|
Loading…
Reference in New Issue