Skip to content

Commit 08d5086

Browse files
authored
Merge pull request #7260 from fhanik/feature/saml2-sp-mvp
Add SAML Service Provider Support
2 parents 08f68c9 + e9a44bc commit 08d5086

File tree

39 files changed

+4260
-19
lines changed

39 files changed

+4260
-19
lines changed

config/spring-security-config.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ dependencies {
1111

1212
optional project(':spring-security-ldap')
1313
optional project(':spring-security-messaging')
14+
optional project(':spring-security-saml2-service-provider')
1415
optional project(':spring-security-oauth2-client')
1516
optional project(':spring-security-oauth2-jose')
1617
optional project(':spring-security-oauth2-resource-server')

config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java

+6
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,19 @@ final class FilterComparator implements Comparator<Filter>, Serializable {
7373
filterToOrder.put(
7474
"org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter",
7575
order.next());
76+
filterToOrder.put(
77+
"org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationRequestFilter",
78+
order.next());
7679
put(X509AuthenticationFilter.class, order.next());
7780
put(AbstractPreAuthenticatedProcessingFilter.class, order.next());
7881
filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter",
7982
order.next());
8083
filterToOrder.put(
8184
"org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter",
8285
order.next());
86+
filterToOrder.put(
87+
"org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter",
88+
order.next());
8389
put(UsernamePasswordAuthenticationFilter.class, order.next());
8490
put(ConcurrentSessionFilter.class, order.next());
8591
filterToOrder.put(

config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java

+190-2
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,13 @@
5353
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer;
5454
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
5555
import org.springframework.security.config.annotation.web.configurers.openid.OpenIDLoginConfigurer;
56+
import org.springframework.security.config.annotation.web.configurers.saml2.Saml2LoginConfigurer;
5657
import org.springframework.security.core.Authentication;
5758
import org.springframework.security.core.context.SecurityContext;
5859
import org.springframework.security.core.context.SecurityContextHolder;
5960
import org.springframework.security.core.userdetails.UserDetailsService;
61+
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
62+
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
6063
import org.springframework.security.web.DefaultSecurityFilterChain;
6164
import org.springframework.security.web.PortMapper;
6265
import org.springframework.security.web.PortMapperImpl;
@@ -75,11 +78,11 @@
7578
import org.springframework.web.filter.CorsFilter;
7679
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
7780

78-
import javax.servlet.Filter;
79-
import javax.servlet.http.HttpServletRequest;
8081
import java.util.ArrayList;
8182
import java.util.List;
8283
import java.util.Map;
84+
import javax.servlet.Filter;
85+
import javax.servlet.http.HttpServletRequest;
8386

8487
/**
8588
* A {@link HttpSecurity} is similar to Spring Security's XML &lt;http&gt; element in the
@@ -1857,6 +1860,191 @@ public HttpSecurity formLogin(Customizer<FormLoginConfigurer<HttpSecurity>> form
18571860
return HttpSecurity.this;
18581861
}
18591862

1863+
/**
1864+
* Configures authentication support using an SAML 2.0 Service Provider.
1865+
* <br>
1866+
* <br>
1867+
*
1868+
* The &quot;authentication flow&quot; is implemented using the <b>Web Browser SSO Profile, using POST and REDIRECT bindings</b>,
1869+
* as documented in the <a target="_blank" href="https://docs.oasis-open.org/security/saml/">SAML V2.0 Core,Profiles and Bindings</a>
1870+
* specifications.
1871+
* <br>
1872+
* <br>
1873+
*
1874+
* As a prerequisite to using this feature, is that you have a SAML v2.0 Identity Provider to provide an assertion.
1875+
* The representation of the Service Provider, the relying party, and the remote Identity Provider, the asserting party
1876+
* is contained within {@link RelyingPartyRegistration}.
1877+
* <br>
1878+
* <br>
1879+
*
1880+
* {@link RelyingPartyRegistration}(s) are composed within a
1881+
* {@link RelyingPartyRegistrationRepository},
1882+
* which is <b>required</b> and must be registered with the {@link ApplicationContext} or
1883+
* configured via <code>saml2Login().relyingPartyRegistrationRepository(..)</code>.
1884+
* <br>
1885+
* <br>
1886+
*
1887+
* The default configuration provides an auto-generated login page at <code>&quot;/login&quot;</code> and
1888+
* redirects to <code>&quot;/login?error&quot;</code> when an authentication error occurs.
1889+
* The login page will display each of the identity providers with a link
1890+
* that is capable of initiating the &quot;authentication flow&quot;.
1891+
* <br>
1892+
* <br>
1893+
*
1894+
* <p>
1895+
* <h2>Example Configuration</h2>
1896+
*
1897+
* The following example shows the minimal configuration required, using SimpleSamlPhp as the Authentication Provider.
1898+
*
1899+
* <pre>
1900+
* &#064;Configuration
1901+
* public class Saml2LoginConfig {
1902+
*
1903+
* &#064;EnableWebSecurity
1904+
* public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
1905+
* &#064;Override
1906+
* protected void configure(HttpSecurity http) throws Exception {
1907+
* http
1908+
* .authorizeRequests()
1909+
* .anyRequest().authenticated()
1910+
* .and()
1911+
* .saml2Login();
1912+
* }
1913+
* }
1914+
*
1915+
* &#064;Bean
1916+
* public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() {
1917+
* return new InMemoryRelyingPartyRegistrationRepository(this.getSaml2RelyingPartyRegistration());
1918+
* }
1919+
*
1920+
* private RelyingPartyRegistration getSaml2RelyingPartyRegistration() {
1921+
* //remote IDP entity ID
1922+
* String idpEntityId = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/metadata.php";
1923+
* //remote WebSSO Endpoint - Where to Send AuthNRequests to
1924+
* String webSsoEndpoint = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php";
1925+
* //local registration ID
1926+
* String registrationId = "simplesamlphp";
1927+
* //local entity ID - autogenerated based on URL
1928+
* String localEntityIdTemplate = "{baseUrl}/saml2/service-provider-metadata/{registrationId}";
1929+
* //local signing (and decryption key)
1930+
* Saml2X509Credential signingCredential = getSigningCredential();
1931+
* //IDP certificate for verification of incoming messages
1932+
* Saml2X509Credential idpVerificationCertificate = getVerificationCertificate();
1933+
* return RelyingPartyRegistration.withRegistrationId(registrationId)
1934+
* * .remoteIdpEntityId(idpEntityId)
1935+
* * .idpWebSsoUrl(webSsoEndpoint)
1936+
* * .credential(signingCredential)
1937+
* * .credential(idpVerificationCertificate)
1938+
* * .localEntityIdTemplate(localEntityIdTemplate)
1939+
* * .build();
1940+
* }
1941+
* }
1942+
* </pre>
1943+
*
1944+
* <p>
1945+
*
1946+
* @since 5.2
1947+
* @return the {@link Saml2LoginConfigurer} for further customizations
1948+
* @throws Exception
1949+
*/
1950+
public Saml2LoginConfigurer<HttpSecurity> saml2Login() throws Exception {
1951+
return getOrApply(new Saml2LoginConfigurer<>());
1952+
}
1953+
1954+
/**
1955+
* Configures authentication support using an SAML 2.0 Service Provider.
1956+
* <br>
1957+
* <br>
1958+
*
1959+
* The &quot;authentication flow&quot; is implemented using the <b>Web Browser SSO Profile, using POST and REDIRECT bindings</b>,
1960+
* as documented in the <a target="_blank" href="https://docs.oasis-open.org/security/saml/">SAML V2.0 Core,Profiles and Bindings</a>
1961+
* specifications.
1962+
* <br>
1963+
* <br>
1964+
*
1965+
* As a prerequisite to using this feature, is that you have a SAML v2.0 Identity Provider to provide an assertion.
1966+
* The representation of the Service Provider, the relying party, and the remote Identity Provider, the asserting party
1967+
* is contained within {@link RelyingPartyRegistration}.
1968+
* <br>
1969+
* <br>
1970+
*
1971+
* {@link RelyingPartyRegistration}(s) are composed within a
1972+
* {@link RelyingPartyRegistrationRepository},
1973+
* which is <b>required</b> and must be registered with the {@link ApplicationContext} or
1974+
* configured via <code>saml2Login().relyingPartyRegistrationRepository(..)</code>.
1975+
* <br>
1976+
* <br>
1977+
*
1978+
* The default configuration provides an auto-generated login page at <code>&quot;/login&quot;</code> and
1979+
* redirects to <code>&quot;/login?error&quot;</code> when an authentication error occurs.
1980+
* The login page will display each of the identity providers with a link
1981+
* that is capable of initiating the &quot;authentication flow&quot;.
1982+
* <br>
1983+
* <br>
1984+
*
1985+
* <p>
1986+
* <h2>Example Configuration</h2>
1987+
*
1988+
* The following example shows the minimal configuration required, using SimpleSamlPhp as the Authentication Provider.
1989+
*
1990+
* <pre>
1991+
* &#064;Configuration
1992+
* public class Saml2LoginConfig {
1993+
*
1994+
* &#064;EnableWebSecurity
1995+
* public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
1996+
* &#064;Override
1997+
* protected void configure(HttpSecurity http) throws Exception {
1998+
* http
1999+
* .authorizeRequests()
2000+
* .anyRequest().authenticated()
2001+
* .and()
2002+
* .saml2Login(withDefaults());
2003+
* }
2004+
* }
2005+
*
2006+
* &#064;Bean
2007+
* public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() {
2008+
* return new InMemoryRelyingPartyRegistrationRepository(this.getSaml2RelyingPartyRegistration());
2009+
* }
2010+
*
2011+
* private RelyingPartyRegistration getSaml2RelyingPartyRegistration() {
2012+
* //remote IDP entity ID
2013+
* String idpEntityId = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/metadata.php";
2014+
* //remote WebSSO Endpoint - Where to Send AuthNRequests to
2015+
* String webSsoEndpoint = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php";
2016+
* //local registration ID
2017+
* String registrationId = "simplesamlphp";
2018+
* //local entity ID - autogenerated based on URL
2019+
* String localEntityIdTemplate = "{baseUrl}/saml2/service-provider-metadata/{registrationId}";
2020+
* //local signing (and decryption key)
2021+
* Saml2X509Credential signingCredential = getSigningCredential();
2022+
* //IDP certificate for verification of incoming messages
2023+
* Saml2X509Credential idpVerificationCertificate = getVerificationCertificate();
2024+
* return RelyingPartyRegistration.withRegistrationId(registrationId)
2025+
* * .remoteIdpEntityId(idpEntityId)
2026+
* * .idpWebSsoUrl(webSsoEndpoint)
2027+
* * .credential(signingCredential)
2028+
* * .credential(idpVerificationCertificate)
2029+
* * .localEntityIdTemplate(localEntityIdTemplate)
2030+
* * .build();
2031+
* }
2032+
* }
2033+
* </pre>
2034+
*
2035+
* <p>
2036+
*
2037+
* @since 5.2
2038+
* @param saml2LoginCustomizer the {@link Customizer} to provide more options for
2039+
* the {@link Saml2LoginConfigurer}
2040+
* @return the {@link HttpSecurity} for further customizations
2041+
* @throws Exception
2042+
*/
2043+
public HttpSecurity saml2Login(Customizer<Saml2LoginConfigurer<HttpSecurity>> saml2LoginCustomizer) throws Exception {
2044+
saml2LoginCustomizer.customize(getOrApply(new Saml2LoginConfigurer<>()));
2045+
return HttpSecurity.this;
2046+
}
2047+
18602048
/**
18612049
* Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 Provider.
18622050
* <br>

0 commit comments

Comments
 (0)