mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-30 00:32:14 +00:00
Improve the Saml2AuthenticationRequest object
- introduce the AssertionConsumerServiceURL attribute - add javadoc - align property name with SAML XML for AuthNRequest
This commit is contained in:
parent
9731386de5
commit
83b5f5c7ae
@ -45,13 +45,14 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication
|
|||||||
auth.setIsPassive(Boolean.FALSE);
|
auth.setIsPassive(Boolean.FALSE);
|
||||||
auth.setProtocolBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect");
|
auth.setProtocolBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect");
|
||||||
Issuer issuer = this.saml.buildSAMLObject(Issuer.class);
|
Issuer issuer = this.saml.buildSAMLObject(Issuer.class);
|
||||||
issuer.setValue(request.getLocalSpEntityId());
|
issuer.setValue(request.getIssuer());
|
||||||
auth.setIssuer(issuer);
|
auth.setIssuer(issuer);
|
||||||
auth.setDestination(request.getWebSsoUri());
|
auth.setDestination(request.getDestination());
|
||||||
|
auth.setAssertionConsumerServiceURL(request.getAssertionConsumerServiceUrl());
|
||||||
return this.saml.toXml(
|
return this.saml.toXml(
|
||||||
auth,
|
auth,
|
||||||
request.getCredentials(),
|
request.getCredentials(),
|
||||||
request.getLocalSpEntityId()
|
request.getIssuer()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,27 +19,36 @@ package org.springframework.security.saml2.provider.service.authentication;
|
|||||||
import org.springframework.security.saml2.credentials.Saml2X509Credential;
|
import org.springframework.security.saml2.credentials.Saml2X509Credential;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data holder for information required to send an {@code AuthNRequest}
|
* Data holder for information required to send an {@code AuthNRequest}
|
||||||
* from the service provider to the identity provider
|
* from the service provider to the identity provider
|
||||||
|
* https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf (line 2031)
|
||||||
*
|
*
|
||||||
* @see {@link Saml2AuthenticationRequestFactory}
|
* @see {@link Saml2AuthenticationRequestFactory}
|
||||||
* @see https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf (line 2031)
|
|
||||||
* @since 5.2
|
* @since 5.2
|
||||||
*/
|
*/
|
||||||
public class Saml2AuthenticationRequest {
|
public final class Saml2AuthenticationRequest {
|
||||||
private final String localSpEntityId;
|
private final String issuer;
|
||||||
private final List<Saml2X509Credential> credentials;
|
private final List<Saml2X509Credential> credentials;
|
||||||
private String webSsoUri;
|
private final String destination;
|
||||||
|
private final String assertionConsumerServiceUrl;
|
||||||
|
|
||||||
public Saml2AuthenticationRequest(String localSpEntityId, String webSsoUri, List<Saml2X509Credential> credentials) {
|
private Saml2AuthenticationRequest(
|
||||||
Assert.hasText(localSpEntityId, "localSpEntityId cannot be null");
|
String issuer,
|
||||||
Assert.hasText(localSpEntityId, "webSsoUri cannot be null");
|
String destination,
|
||||||
this.localSpEntityId = localSpEntityId;
|
String assertionConsumerServiceUrl,
|
||||||
this.webSsoUri = webSsoUri;
|
List<Saml2X509Credential> credentials) {
|
||||||
|
Assert.hasText(issuer, "issuer cannot be null");
|
||||||
|
Assert.hasText(destination, "destination cannot be null");
|
||||||
|
Assert.hasText(assertionConsumerServiceUrl, "spAssertionConsumerServiceUrl cannot be null");
|
||||||
|
this.issuer = issuer;
|
||||||
|
this.destination = destination;
|
||||||
|
this.assertionConsumerServiceUrl = assertionConsumerServiceUrl;
|
||||||
this.credentials = new LinkedList<>();
|
this.credentials = new LinkedList<>();
|
||||||
for (Saml2X509Credential c : credentials) {
|
for (Saml2X509Credential c : credentials) {
|
||||||
if (c.isSigningCredential()) {
|
if (c.isSigningCredential()) {
|
||||||
@ -50,15 +59,126 @@ public class Saml2AuthenticationRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getLocalSpEntityId() {
|
/**
|
||||||
return this.localSpEntityId;
|
* returns the issuer, the local SP entity ID, for this authentication request.
|
||||||
|
* This property should be used to populate the {@code AuthNRequest.Issuer} XML element.
|
||||||
|
* This value typically is a URI, but can be an arbitrary string.
|
||||||
|
* @return issuer
|
||||||
|
*/
|
||||||
|
public String getIssuer() {
|
||||||
|
return this.issuer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWebSsoUri() {
|
/**
|
||||||
return this.webSsoUri;
|
* returns the destination, the WEB Single Sign On URI, for this authentication request.
|
||||||
|
* This property populates the {@code AuthNRequest#Destination} XML attribute.
|
||||||
|
* @return destination
|
||||||
|
*/
|
||||||
|
public String getDestination() {
|
||||||
|
return this.destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the desired {@code AssertionConsumerServiceUrl} that this SP wishes to receive the
|
||||||
|
* assertion on. The IDP may or may not honor this request.
|
||||||
|
* This property populates the {@code AuthNRequest#AssertionConsumerServiceURL} XML attribute.
|
||||||
|
* @return the AssertionConsumerServiceURL value
|
||||||
|
*/
|
||||||
|
public String getAssertionConsumerServiceUrl() {
|
||||||
|
return assertionConsumerServiceUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of credentials that can be used to sign the {@code AuthNRequest} object
|
||||||
|
* @return signing credentials
|
||||||
|
*/
|
||||||
public List<Saml2X509Credential> getCredentials() {
|
public List<Saml2X509Credential> getCredentials() {
|
||||||
return this.credentials;
|
return this.credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder for {@link Saml2AuthenticationRequest}.
|
||||||
|
* returns a builder object
|
||||||
|
*/
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder for {@link Saml2AuthenticationRequest}.
|
||||||
|
*/
|
||||||
|
public static class Builder {
|
||||||
|
private String issuer;
|
||||||
|
private List<Saml2X509Credential> credentials = new LinkedList<>();
|
||||||
|
private String destination;
|
||||||
|
private String assertionConsumerServiceUrl;
|
||||||
|
|
||||||
|
private Builder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the issuer for the authentication request.
|
||||||
|
* @param issuer - a required value
|
||||||
|
* @return this {@code Builder}
|
||||||
|
*/
|
||||||
|
public Builder issuer(String issuer) {
|
||||||
|
this.issuer = issuer;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifies the collection of {@link Saml2X509Credential} credentials
|
||||||
|
* used in communication between IDP and SP, specifically signing the
|
||||||
|
* authentication request.
|
||||||
|
* For example:
|
||||||
|
* <code>
|
||||||
|
* Saml2X509Credential credential = ...;
|
||||||
|
* return Saml2AuthenticationRequest.withLocalSpEntityId("id")
|
||||||
|
* .credentials(c -> c.add(credential))
|
||||||
|
* ...
|
||||||
|
* .build();
|
||||||
|
* </code>
|
||||||
|
* @param credentials - a consumer that can modify the collection of credentials
|
||||||
|
* @return this object
|
||||||
|
*/
|
||||||
|
public Builder credentials(Consumer<Collection<Saml2X509Credential>> credentials) {
|
||||||
|
credentials.accept(this.credentials);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the Destination for the authentication request. Typically the {@code Service Provider EntityID}
|
||||||
|
* @param destination - a required value
|
||||||
|
* @return this {@code Builder}
|
||||||
|
*/
|
||||||
|
public Builder destination(String destination) {
|
||||||
|
this.destination = destination;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@code assertionConsumerServiceURL} for the authentication request.
|
||||||
|
* Typically the {@code Service Provider EntityID}
|
||||||
|
* @param assertionConsumerServiceUrl - a required value
|
||||||
|
* @return this {@code Builder}
|
||||||
|
*/
|
||||||
|
public Builder assertionConsumerServiceUrl(String assertionConsumerServiceUrl) {
|
||||||
|
this.assertionConsumerServiceUrl = assertionConsumerServiceUrl;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link Saml2AuthenticationRequest} object.
|
||||||
|
* @return the Saml2AuthenticationRequest object
|
||||||
|
* @throws {@link IllegalArgumentException} if a required property is not set
|
||||||
|
*/
|
||||||
|
public Saml2AuthenticationRequest build() {
|
||||||
|
return new Saml2AuthenticationRequest(
|
||||||
|
this.issuer,
|
||||||
|
this.destination,
|
||||||
|
this.assertionConsumerServiceUrl,
|
||||||
|
this.credentials
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,11 +105,20 @@ public class Saml2WebSsoAuthenticationRequestFilter extends OncePerRequestFilter
|
|||||||
|
|
||||||
private Saml2AuthenticationRequest createAuthenticationRequest(RelyingPartyRegistration relyingParty, HttpServletRequest request) {
|
private Saml2AuthenticationRequest createAuthenticationRequest(RelyingPartyRegistration relyingParty, HttpServletRequest request) {
|
||||||
String localSpEntityId = Saml2Utils.getServiceProviderEntityId(relyingParty, request);
|
String localSpEntityId = Saml2Utils.getServiceProviderEntityId(relyingParty, request);
|
||||||
return new Saml2AuthenticationRequest(
|
return Saml2AuthenticationRequest
|
||||||
localSpEntityId,
|
.builder()
|
||||||
relyingParty.getIdpWebSsoUrl(),
|
.issuer(localSpEntityId)
|
||||||
relyingParty.getSigningCredentials()
|
.destination(relyingParty.getIdpWebSsoUrl())
|
||||||
);
|
.credentials(c -> c.addAll(relyingParty.getCredentials()))
|
||||||
|
.assertionConsumerServiceUrl(
|
||||||
|
Saml2Utils.resolveUrlTemplate(
|
||||||
|
relyingParty.getAssertionConsumerServiceUrlTemplate(),
|
||||||
|
Saml2Utils.getApplicationUri(request),
|
||||||
|
relyingParty.getRemoteIdpEntityId(),
|
||||||
|
relyingParty.getRegistrationId()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -160,6 +160,13 @@ public class Saml2LoginIntegrationTests {
|
|||||||
"https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php",
|
"https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php",
|
||||||
destination
|
destination
|
||||||
);
|
);
|
||||||
|
String acsURL = authnRequest.getAssertionConsumerServiceURL();
|
||||||
|
assertEquals(
|
||||||
|
"AssertionConsumerServiceURL must match",
|
||||||
|
"http://localhost:8080/login/saml2/sso/simplesamlphp",
|
||||||
|
acsURL
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user