Skip to content

Commit 475b1d6

Browse files
Add SAML 2.0 Login XML Support
Closes gh-9012
1 parent c2635ba commit 475b1d6

File tree

32 files changed

+2655
-9
lines changed

32 files changed

+2655
-9
lines changed

config/src/main/java/org/springframework/security/config/Elements.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -138,4 +138,8 @@ public abstract class Elements {
138138

139139
public static final String PASSWORD_MANAGEMENT = "password-management";
140140

141+
public static final String RELYING_PARTY_REGISTRATIONS = "relying-party-registrations";
142+
143+
public static final String SAML2_LOGIN = "saml2-login";
144+
141145
}

config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2020 the original author or authors.
2+
* Copyright 2009-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -47,6 +47,7 @@
4747
import org.springframework.security.config.method.MethodSecurityBeanDefinitionParser;
4848
import org.springframework.security.config.method.MethodSecurityMetadataSourceBeanDefinitionParser;
4949
import org.springframework.security.config.oauth2.client.ClientRegistrationsBeanDefinitionParser;
50+
import org.springframework.security.config.saml2.RelyingPartyRegistrationsBeanDefinitionParser;
5051
import org.springframework.security.config.websocket.WebSocketMessageBrokerSecurityBeanDefinitionParser;
5152
import org.springframework.security.core.SpringSecurityCoreVersion;
5253
import org.springframework.util.ClassUtils;
@@ -190,6 +191,7 @@ private void loadWebParsers() {
190191
this.parsers.put(Elements.FILTER_CHAIN, new FilterChainBeanDefinitionParser());
191192
this.filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator();
192193
this.parsers.put(Elements.CLIENT_REGISTRATIONS, new ClientRegistrationsBeanDefinitionParser());
194+
this.parsers.put(Elements.RELYING_PARTY_REGISTRATIONS, new RelyingPartyRegistrationsBeanDefinitionParser());
193195
}
194196

195197
private void loadWebSocketParsers() {

config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -202,6 +202,14 @@ final class AuthenticationConfigBuilder {
202202

203203
private BeanDefinition oauth2LoginLinks;
204204

205+
private BeanDefinition saml2AuthenticationUrlToProviderName;
206+
207+
private BeanDefinition saml2AuthorizationRequestFilter;
208+
209+
private String saml2AuthenticationFilterId;
210+
211+
private String saml2AuthenticationRequestFilterId;
212+
205213
private boolean oauth2ClientEnabled;
206214

207215
private BeanDefinition authorizationRequestRedirectFilter;
@@ -238,6 +246,7 @@ final class AuthenticationConfigBuilder {
238246
createFormLoginFilter(sessionStrategy, authenticationManager);
239247
createOAuth2ClientFilters(sessionStrategy, requestCache, authenticationManager);
240248
createOpenIDLoginFilter(sessionStrategy, authenticationManager);
249+
createSaml2LoginFilter(authenticationManager);
241250
createX509Filter(authenticationManager);
242251
createJeeFilter(authenticationManager);
243252
createLogoutFilter();
@@ -412,6 +421,29 @@ void createOpenIDLoginFilter(BeanReference sessionStrategy, BeanReference authMa
412421
}
413422
}
414423

424+
private void createSaml2LoginFilter(BeanReference authenticationManager) {
425+
Element saml2LoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.SAML2_LOGIN);
426+
if (saml2LoginElt == null) {
427+
return;
428+
}
429+
Saml2LoginBeanDefinitionParser parser = new Saml2LoginBeanDefinitionParser(this.csrfIgnoreRequestMatchers,
430+
this.portMapper, this.portResolver, this.requestCache, this.allowSessionCreation, authenticationManager,
431+
this.authenticationProviders, this.defaultEntryPointMappings);
432+
BeanDefinition saml2WebSsoAuthenticationFilter = parser.parse(saml2LoginElt, this.pc);
433+
this.saml2AuthorizationRequestFilter = parser.getSaml2WebSsoAuthenticationRequestFilter();
434+
435+
this.saml2AuthenticationFilterId = this.pc.getReaderContext().generateBeanName(saml2WebSsoAuthenticationFilter);
436+
this.saml2AuthenticationRequestFilterId = this.pc.getReaderContext()
437+
.generateBeanName(this.saml2AuthorizationRequestFilter);
438+
this.saml2AuthenticationUrlToProviderName = parser.getSaml2AuthenticationUrlToProviderName();
439+
440+
// register the component
441+
this.pc.registerBeanComponent(
442+
new BeanComponentDefinition(saml2WebSsoAuthenticationFilter, this.saml2AuthenticationFilterId));
443+
this.pc.registerBeanComponent(new BeanComponentDefinition(this.saml2AuthorizationRequestFilter,
444+
this.saml2AuthenticationRequestFilterId));
445+
}
446+
415447
/**
416448
* Parses OpenID 1.0 and 2.0 - related parts of configuration xmls
417449
* @param sessionStrategy sessionStrategy
@@ -666,6 +698,12 @@ void createLoginPageFilterIfNeeded() {
666698
loginPageFilter.addPropertyValue("Oauth2LoginEnabled", true);
667699
loginPageFilter.addPropertyValue("Oauth2AuthenticationUrlToClientName", this.oauth2LoginLinks);
668700
}
701+
if (this.saml2AuthenticationFilterId != null) {
702+
loginPageFilter.addConstructorArgReference(this.saml2AuthenticationFilterId);
703+
loginPageFilter.addPropertyValue("saml2LoginEnabled", true);
704+
loginPageFilter.addPropertyValue("saml2AuthenticationUrlToProviderName",
705+
this.saml2AuthenticationUrlToProviderName);
706+
}
669707
this.loginPageGenerationFilter = loginPageFilter.getBeanDefinition();
670708
this.logoutPageGenerationFilter = logoutPageFilter.getBeanDefinition();
671709
}
@@ -840,7 +878,8 @@ private BeanMetadataElement selectEntryPoint() {
840878
if (formLoginElt != null && this.oauth2LoginEntryPoint != null) {
841879
return this.formEntryPoint;
842880
}
843-
// If form login was enabled through auto-config, and Oauth2 login was not
881+
// If form login was enabled through auto-config, and Oauth2 login & Saml2
882+
// login was not
844883
// enabled then use form login
845884
if (this.oauth2LoginEntryPoint == null) {
846885
return this.formEntryPoint;
@@ -923,6 +962,12 @@ List<OrderDecorator> getFilters() {
923962
filters.add(new OrderDecorator(this.authorizationCodeGrantFilter,
924963
SecurityFilters.OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER));
925964
}
965+
if (this.saml2AuthenticationFilterId != null) {
966+
filters.add(new OrderDecorator(new RuntimeBeanReference(this.saml2AuthenticationFilterId),
967+
SecurityFilters.SAML2_AUTHENTICATION_FILTER));
968+
filters.add(new OrderDecorator(new RuntimeBeanReference(this.saml2AuthenticationRequestFilterId),
969+
SecurityFilters.SAML2_AUTHENTICATION_REQUEST_FILTER));
970+
}
926971
filters.add(new OrderDecorator(this.etf, SecurityFilters.EXCEPTION_TRANSLATION_FILTER));
927972
return filters;
928973
}

0 commit comments

Comments
 (0)