AuthenticationConfigBuilder.java
/*
* Copyright 2004-present the original author or authors.
*
* 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
*
* https://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 org.springframework.security.config.http;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Element;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.authentication.AnonymousAuthenticationProvider;
import org.springframework.security.authentication.RememberMeAuthenticationProvider;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.Elements;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper;
import org.springframework.security.core.authority.mapping.SimpleMappableAttributesRetriever;
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
import org.springframework.security.web.access.ExceptionTranslationFilter;
import org.springframework.security.web.access.RequestMatcherDelegatingAccessDeniedHandler;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService;
import org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter;
import org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor;
import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
import org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter;
import org.springframework.security.web.authentication.ui.DefaultResourcesFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
/**
* Handles creation of authentication mechanism filters and related beans for <http>
* parsing.
*
* @author Luke Taylor
* @author Rob Winch
* @since 3.0
*/
final class AuthenticationConfigBuilder {
private final Log logger = LogFactory.getLog(getClass());
private static final boolean webMvcPresent;
private static final String ATT_REALM = "realm";
private static final String DEF_REALM = "Realm";
static final String AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter";
static final String ATT_AUTH_DETAILS_SOURCE_REF = "authentication-details-source-ref";
private static final String ATT_AUTO_CONFIG = "auto-config";
private static final String ATT_ACCESS_DENIED_ERROR_PAGE = "error-page";
private static final String ATT_ENTRY_POINT_REF = "entry-point-ref";
private static final String ATT_USER_SERVICE_REF = "user-service-ref";
private static final String ATT_KEY = "key";
private static final String ATT_MAPPABLE_ROLES = "mappable-roles";
private final Element httpElt;
private final ParserContext pc;
private final boolean autoConfig;
private final boolean allowSessionCreation;
private RootBeanDefinition anonymousFilter;
private BeanReference anonymousProviderRef;
private BeanDefinition rememberMeFilter;
private String rememberMeServicesId;
private BeanReference rememberMeProviderRef;
private BeanDefinition basicFilter;
private RuntimeBeanReference basicEntryPoint;
private BeanDefinition formEntryPoint;
private String formFilterId = null;
private BeanDefinition x509Filter;
private BeanReference x509ProviderRef;
private BeanDefinition jeeFilter;
private BeanReference jeeProviderRef;
private RootBeanDefinition preAuthEntryPoint;
private BeanMetadataElement mainEntryPoint;
private BeanMetadataElement accessDeniedHandler;
private BeanDefinition bearerTokenAuthenticationFilter;
private BeanDefinition logoutFilter;
@SuppressWarnings("rawtypes")
private ManagedList logoutHandlers;
private BeanMetadataElement logoutSuccessHandler;
private BeanDefinition loginPageGenerationFilter;
private BeanDefinition logoutPageGenerationFilter;
private BeanDefinition defaultResourcesFilter;
private BeanDefinition etf;
private final BeanReference requestCache;
private final BeanReference portMapper;
private final BeanMetadataElement csrfLogoutHandler;
private String loginProcessingUrl;
private String formLoginPage;
private boolean oauth2LoginEnabled;
private boolean defaultAuthorizedClientRepositoryRegistered;
private String oauth2LoginFilterId;
private BeanDefinition oauth2AuthorizationRequestRedirectFilter;
private BeanDefinition oauth2LoginEntryPoint;
private BeanReference oauth2LoginAuthenticationProviderRef;
private BeanReference oauth2LoginOidcAuthenticationProviderRef;
private BeanDefinition oauth2LoginLinks;
private BeanDefinition saml2AuthenticationUrlToProviderName;
private BeanDefinition saml2AuthorizationRequestFilter;
private String saml2AuthenticationFilterId;
private String saml2AuthenticationRequestFilterId;
private String saml2LogoutFilterId;
private String saml2LogoutRequestFilterId;
private String saml2LogoutResponseFilterId;
private boolean oauth2ClientEnabled;
private BeanDefinition authorizationRequestRedirectFilter;
private BeanDefinition authorizationCodeGrantFilter;
private BeanReference authorizationCodeAuthenticationProviderRef;
private final List<BeanReference> authenticationProviders = new ManagedList<>();
private final Map<BeanDefinition, BeanMetadataElement> defaultDeniedHandlerMappings = new ManagedMap<>();
private final Map<BeanDefinition, BeanMetadataElement> defaultEntryPointMappings = new ManagedMap<>();
private final List<BeanDefinition> csrfIgnoreRequestMatchers = new ManagedList<>();
static {
ClassLoader classLoader = AuthenticationConfigBuilder.class.getClassLoader();
webMvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", classLoader);
}
AuthenticationConfigBuilder(Element element, boolean forceAutoConfig, ParserContext pc,
SessionCreationPolicy sessionPolicy, BeanReference requestCache, BeanReference authenticationManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef,
BeanReference authenticationFilterSecurityContextRepositoryRef, BeanReference sessionStrategy,
BeanReference portMapper, BeanMetadataElement csrfLogoutHandler) {
this.httpElt = element;
this.pc = pc;
this.requestCache = requestCache;
this.autoConfig = forceAutoConfig | "true".equals(element.getAttribute(ATT_AUTO_CONFIG));
this.allowSessionCreation = sessionPolicy != SessionCreationPolicy.NEVER
&& sessionPolicy != SessionCreationPolicy.STATELESS;
this.portMapper = portMapper;
this.csrfLogoutHandler = csrfLogoutHandler;
createAnonymousFilter(authenticationFilterSecurityContextHolderStrategyRef);
createRememberMeFilter(authenticationManager, authenticationFilterSecurityContextHolderStrategyRef);
createBasicFilter(authenticationManager, authenticationFilterSecurityContextHolderStrategyRef);
createBearerTokenAuthenticationFilter(authenticationManager,
authenticationFilterSecurityContextHolderStrategyRef);
createFormLoginFilter(sessionStrategy, authenticationManager,
authenticationFilterSecurityContextHolderStrategyRef, authenticationFilterSecurityContextRepositoryRef);
createOAuth2ClientFilters(sessionStrategy, requestCache, authenticationManager,
authenticationFilterSecurityContextRepositoryRef, authenticationFilterSecurityContextHolderStrategyRef);
createSaml2LoginFilter(authenticationManager, authenticationFilterSecurityContextRepositoryRef);
createX509Filter(authenticationManager, authenticationFilterSecurityContextHolderStrategyRef);
createJeeFilter(authenticationManager, authenticationFilterSecurityContextHolderStrategyRef);
createLogoutFilter(authenticationFilterSecurityContextHolderStrategyRef);
createSaml2LogoutFilter(authenticationFilterSecurityContextHolderStrategyRef);
createLoginPageFilterIfNeeded();
createUserDetailsServiceFactory();
createExceptionTranslationFilter(authenticationFilterSecurityContextHolderStrategyRef);
}
void createRememberMeFilter(BeanReference authenticationManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
// Parse remember me before logout as RememberMeServices is also a LogoutHandler
// implementation.
Element rememberMeElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.REMEMBER_ME);
if (rememberMeElt != null) {
String key = rememberMeElt.getAttribute(ATT_KEY);
if (!StringUtils.hasText(key)) {
key = createKey();
}
RememberMeBeanDefinitionParser rememberMeParser = new RememberMeBeanDefinitionParser(key,
authenticationManager, authenticationFilterSecurityContextHolderStrategyRef);
this.rememberMeFilter = rememberMeParser.parse(rememberMeElt, this.pc);
this.rememberMeServicesId = rememberMeParser.getRememberMeServicesId();
createRememberMeProvider(key);
}
}
private void createRememberMeProvider(String key) {
RootBeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class);
provider.setSource(this.rememberMeFilter.getSource());
provider.getConstructorArgumentValues().addGenericArgumentValue(key);
String id = this.pc.getReaderContext().generateBeanName(provider);
this.pc.registerBeanComponent(new BeanComponentDefinition(provider, id));
this.rememberMeProviderRef = new RuntimeBeanReference(id);
}
void createFormLoginFilter(BeanReference sessionStrategy, BeanReference authManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef,
BeanReference authenticationFilterSecurityContextRepositoryRef) {
Element formLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.FORM_LOGIN);
RootBeanDefinition formFilter = null;
if (formLoginElt != null || this.autoConfig) {
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/login", "POST",
AUTHENTICATION_PROCESSING_FILTER_CLASS, this.requestCache, sessionStrategy,
this.allowSessionCreation, this.portMapper);
parser.parse(formLoginElt, this.pc);
formFilter = parser.getFilterBean();
this.formEntryPoint = parser.getEntryPointBean();
this.loginProcessingUrl = parser.getLoginProcessingUrl();
this.formLoginPage = parser.getLoginPage();
}
if (formFilter != null) {
formFilter.getPropertyValues().addPropertyValue("allowSessionCreation", this.allowSessionCreation);
formFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
if (authenticationFilterSecurityContextRepositoryRef != null) {
formFilter.getPropertyValues()
.addPropertyValue("securityContextRepository", authenticationFilterSecurityContextRepositoryRef);
}
formFilter.getPropertyValues()
.addPropertyValue("securityContextHolderStrategy",
authenticationFilterSecurityContextHolderStrategyRef);
// Id is required by login page filter
this.formFilterId = this.pc.getReaderContext().generateBeanName(formFilter);
this.pc.registerBeanComponent(new BeanComponentDefinition(formFilter, this.formFilterId));
injectRememberMeServicesRef(formFilter, this.rememberMeServicesId);
}
}
void createOAuth2ClientFilters(BeanReference sessionStrategy, BeanReference requestCache,
BeanReference authenticationManager, BeanReference authenticationFilterSecurityContextRepositoryRef,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategy) {
createOAuth2LoginFilter(sessionStrategy, authenticationManager,
authenticationFilterSecurityContextRepositoryRef, authenticationFilterSecurityContextHolderStrategy);
createOAuth2ClientFilter(requestCache, authenticationManager, authenticationFilterSecurityContextRepositoryRef,
authenticationFilterSecurityContextHolderStrategy);
registerOAuth2ClientPostProcessors();
}
void createOAuth2LoginFilter(BeanReference sessionStrategy, BeanReference authManager,
BeanReference authenticationFilterSecurityContextRepositoryRef,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategy) {
Element oauth2LoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OAUTH2_LOGIN);
if (oauth2LoginElt == null) {
return;
}
this.oauth2LoginEnabled = true;
OAuth2LoginBeanDefinitionParser parser = new OAuth2LoginBeanDefinitionParser(this.requestCache, this.portMapper,
sessionStrategy, this.allowSessionCreation, authenticationFilterSecurityContextHolderStrategy);
BeanDefinition oauth2LoginFilterBean = parser.parse(oauth2LoginElt, this.pc);
BeanDefinition defaultAuthorizedClientRepository = parser.getDefaultAuthorizedClientRepository();
registerDefaultAuthorizedClientRepositoryIfNecessary(defaultAuthorizedClientRepository);
oauth2LoginFilterBean.getPropertyValues().addPropertyValue("authenticationManager", authManager);
if (authenticationFilterSecurityContextRepositoryRef != null) {
oauth2LoginFilterBean.getPropertyValues()
.addPropertyValue("securityContextRepository", authenticationFilterSecurityContextRepositoryRef);
}
// retrieve the other bean result
BeanDefinition oauth2LoginAuthProvider = parser.getOAuth2LoginAuthenticationProvider();
this.oauth2AuthorizationRequestRedirectFilter = parser.getOAuth2AuthorizationRequestRedirectFilter();
this.oauth2LoginEntryPoint = parser.getOAuth2LoginAuthenticationEntryPoint();
// generate bean name to be registered
String oauth2LoginAuthProviderId = this.pc.getReaderContext().generateBeanName(oauth2LoginAuthProvider);
this.oauth2LoginFilterId = this.pc.getReaderContext().generateBeanName(oauth2LoginFilterBean);
String oauth2AuthorizationRequestRedirectFilterId = this.pc.getReaderContext()
.generateBeanName(this.oauth2AuthorizationRequestRedirectFilter);
this.oauth2LoginLinks = parser.getOAuth2LoginLinks();
// register the component
this.pc.registerBeanComponent(new BeanComponentDefinition(oauth2LoginFilterBean, this.oauth2LoginFilterId));
this.pc.registerBeanComponent(new BeanComponentDefinition(this.oauth2AuthorizationRequestRedirectFilter,
oauth2AuthorizationRequestRedirectFilterId));
this.pc.registerBeanComponent(new BeanComponentDefinition(oauth2LoginAuthProvider, oauth2LoginAuthProviderId));
this.oauth2LoginAuthenticationProviderRef = new RuntimeBeanReference(oauth2LoginAuthProviderId);
// oidc provider
BeanDefinition oauth2LoginOidcAuthProvider = parser.getOAuth2LoginOidcAuthenticationProvider();
String oauth2LoginOidcAuthProviderId = this.pc.getReaderContext().generateBeanName(oauth2LoginOidcAuthProvider);
this.pc.registerBeanComponent(
new BeanComponentDefinition(oauth2LoginOidcAuthProvider, oauth2LoginOidcAuthProviderId));
this.oauth2LoginOidcAuthenticationProviderRef = new RuntimeBeanReference(oauth2LoginOidcAuthProviderId);
}
void createOAuth2ClientFilter(BeanReference requestCache, BeanReference authenticationManager,
BeanReference authenticationFilterSecurityContextRepositoryRef,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategy) {
Element oauth2ClientElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OAUTH2_CLIENT);
if (oauth2ClientElt == null) {
return;
}
this.oauth2ClientEnabled = true;
OAuth2ClientBeanDefinitionParser parser = new OAuth2ClientBeanDefinitionParser(requestCache,
authenticationManager, authenticationFilterSecurityContextRepositoryRef,
authenticationFilterSecurityContextHolderStrategy);
parser.parse(oauth2ClientElt, this.pc);
BeanDefinition defaultAuthorizedClientRepository = parser.getDefaultAuthorizedClientRepository();
registerDefaultAuthorizedClientRepositoryIfNecessary(defaultAuthorizedClientRepository);
this.authorizationRequestRedirectFilter = parser.getAuthorizationRequestRedirectFilter();
String authorizationRequestRedirectFilterId = this.pc.getReaderContext()
.generateBeanName(this.authorizationRequestRedirectFilter);
this.pc.registerBeanComponent(new BeanComponentDefinition(this.authorizationRequestRedirectFilter,
authorizationRequestRedirectFilterId));
this.authorizationCodeGrantFilter = parser.getAuthorizationCodeGrantFilter();
String authorizationCodeGrantFilterId = this.pc.getReaderContext()
.generateBeanName(this.authorizationCodeGrantFilter);
this.pc.registerBeanComponent(
new BeanComponentDefinition(this.authorizationCodeGrantFilter, authorizationCodeGrantFilterId));
BeanDefinition authorizationCodeAuthenticationProvider = parser.getAuthorizationCodeAuthenticationProvider();
String authorizationCodeAuthenticationProviderId = this.pc.getReaderContext()
.generateBeanName(authorizationCodeAuthenticationProvider);
this.pc.registerBeanComponent(new BeanComponentDefinition(authorizationCodeAuthenticationProvider,
authorizationCodeAuthenticationProviderId));
this.authorizationCodeAuthenticationProviderRef = new RuntimeBeanReference(
authorizationCodeAuthenticationProviderId);
}
void registerDefaultAuthorizedClientRepositoryIfNecessary(BeanDefinition defaultAuthorizedClientRepository) {
if (!this.defaultAuthorizedClientRepositoryRegistered && defaultAuthorizedClientRepository != null) {
String authorizedClientRepositoryId = this.pc.getReaderContext()
.generateBeanName(defaultAuthorizedClientRepository);
this.pc.registerBeanComponent(
new BeanComponentDefinition(defaultAuthorizedClientRepository, authorizedClientRepositoryId));
this.defaultAuthorizedClientRepositoryRegistered = true;
}
}
private void registerOAuth2ClientPostProcessors() {
if (!this.oauth2LoginEnabled && !this.oauth2ClientEnabled) {
return;
}
if (webMvcPresent) {
this.pc.getReaderContext()
.registerWithGeneratedName(new RootBeanDefinition(OAuth2ClientWebMvcSecurityPostProcessor.class));
}
this.pc.getReaderContext()
.getRegistry()
.registerBeanDefinition(OAuth2AuthorizedClientManagerRegistrar.BEAN_NAME,
new RootBeanDefinition(OAuth2AuthorizedClientManagerRegistrar.class));
}
private void createSaml2LoginFilter(BeanReference authenticationManager,
BeanReference authenticationFilterSecurityContextRepositoryRef) {
Element saml2LoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.SAML2_LOGIN);
if (saml2LoginElt == null) {
return;
}
Saml2LoginBeanDefinitionParser parser = new Saml2LoginBeanDefinitionParser(this.csrfIgnoreRequestMatchers,
this.portMapper, this.requestCache, this.allowSessionCreation, authenticationManager,
authenticationFilterSecurityContextRepositoryRef, this.authenticationProviders,
this.defaultEntryPointMappings);
BeanDefinition saml2WebSsoAuthenticationFilter = parser.parse(saml2LoginElt, this.pc);
this.saml2AuthorizationRequestFilter = parser.getSaml2WebSsoAuthenticationRequestFilter();
this.saml2AuthenticationFilterId = this.pc.getReaderContext().generateBeanName(saml2WebSsoAuthenticationFilter);
this.saml2AuthenticationRequestFilterId = this.pc.getReaderContext()
.generateBeanName(this.saml2AuthorizationRequestFilter);
this.saml2AuthenticationUrlToProviderName = parser.getSaml2AuthenticationUrlToProviderName();
// register the component
this.pc.registerBeanComponent(
new BeanComponentDefinition(saml2WebSsoAuthenticationFilter, this.saml2AuthenticationFilterId));
this.pc.registerBeanComponent(new BeanComponentDefinition(this.saml2AuthorizationRequestFilter,
this.saml2AuthenticationRequestFilterId));
}
private void injectRememberMeServicesRef(RootBeanDefinition bean, String rememberMeServicesId) {
if (rememberMeServicesId != null) {
bean.getPropertyValues()
.addPropertyValue("rememberMeServices", new RuntimeBeanReference(rememberMeServicesId));
}
}
void createBasicFilter(BeanReference authManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
Element basicAuthElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.BASIC_AUTH);
if (basicAuthElt == null && !this.autoConfig) {
// No basic auth, do nothing
return;
}
String realm = this.httpElt.getAttribute(ATT_REALM);
if (!StringUtils.hasText(realm)) {
realm = DEF_REALM;
}
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicAuthenticationFilter.class);
String entryPointId;
if (basicAuthElt != null) {
if (StringUtils.hasText(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF))) {
this.basicEntryPoint = new RuntimeBeanReference(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF));
}
injectAuthenticationDetailsSource(basicAuthElt, filterBuilder);
}
if (this.basicEntryPoint == null) {
RootBeanDefinition entryPoint = new RootBeanDefinition(BasicAuthenticationEntryPoint.class);
entryPoint.setSource(this.pc.extractSource(this.httpElt));
entryPoint.getPropertyValues().addPropertyValue("realmName", realm);
entryPointId = this.pc.getReaderContext().generateBeanName(entryPoint);
this.pc.registerBeanComponent(new BeanComponentDefinition(entryPoint, entryPointId));
this.basicEntryPoint = new RuntimeBeanReference(entryPointId);
}
filterBuilder.addConstructorArgValue(authManager);
filterBuilder.addConstructorArgValue(this.basicEntryPoint);
filterBuilder.addPropertyValue("securityContextHolderStrategy",
authenticationFilterSecurityContextHolderStrategyRef);
this.basicFilter = filterBuilder.getBeanDefinition();
}
void createBearerTokenAuthenticationFilter(BeanReference authManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
Element resourceServerElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OAUTH2_RESOURCE_SERVER);
if (resourceServerElt == null) {
// No resource server, do nothing
return;
}
OAuth2ResourceServerBeanDefinitionParser resourceServerBuilder = new OAuth2ResourceServerBeanDefinitionParser(
authManager, this.authenticationProviders, this.defaultEntryPointMappings,
this.defaultDeniedHandlerMappings, this.csrfIgnoreRequestMatchers,
authenticationFilterSecurityContextHolderStrategyRef);
this.bearerTokenAuthenticationFilter = resourceServerBuilder.parse(resourceServerElt, this.pc);
}
void createX509Filter(BeanReference authManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
Element x509Elt = DomUtils.getChildElementByTagName(this.httpElt, Elements.X509);
RootBeanDefinition filter = null;
if (x509Elt != null) {
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder
.rootBeanDefinition(X509AuthenticationFilter.class);
filterBuilder.getRawBeanDefinition().setSource(this.pc.extractSource(x509Elt));
filterBuilder.addPropertyValue("authenticationManager", authManager);
filterBuilder.addPropertyValue("securityContextHolderStrategy",
authenticationFilterSecurityContextHolderStrategyRef);
String principalExtractorRef = x509Elt.getAttribute("principal-extractor-ref");
String subjectPrincipalRegex = x509Elt.getAttribute("subject-principal-regex");
boolean hasPrincipalExtractorRef = StringUtils.hasText(principalExtractorRef);
boolean hasSubjectPrincipalRegex = StringUtils.hasText(subjectPrincipalRegex);
if (hasPrincipalExtractorRef && hasSubjectPrincipalRegex) {
this.pc.getReaderContext()
.error("The attribute 'principal-extractor-ref' cannot be used together with the 'subject-principal-regex' attribute within <"
+ Elements.X509 + ">", this.pc.extractSource(x509Elt));
}
if (hasPrincipalExtractorRef) {
RuntimeBeanReference principalExtractor = new RuntimeBeanReference(principalExtractorRef);
filterBuilder.addPropertyValue("principalExtractor", principalExtractor);
}
if (hasSubjectPrincipalRegex) {
BeanDefinitionBuilder extractor = BeanDefinitionBuilder
.rootBeanDefinition(SubjectDnX509PrincipalExtractor.class);
extractor.addPropertyValue("subjectDnRegex", subjectPrincipalRegex);
filterBuilder.addPropertyValue("principalExtractor", extractor.getBeanDefinition());
}
injectAuthenticationDetailsSource(x509Elt, filterBuilder);
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
createPrauthEntryPoint(x509Elt);
createX509Provider();
}
this.x509Filter = filter;
}
private void injectAuthenticationDetailsSource(Element elt, BeanDefinitionBuilder filterBuilder) {
String authDetailsSourceRef = elt.getAttribute(AuthenticationConfigBuilder.ATT_AUTH_DETAILS_SOURCE_REF);
if (StringUtils.hasText(authDetailsSourceRef)) {
filterBuilder.addPropertyReference("authenticationDetailsSource", authDetailsSourceRef);
}
}
private void createX509Provider() {
Element x509Elt = DomUtils.getChildElementByTagName(this.httpElt, Elements.X509);
BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
RootBeanDefinition uds = new RootBeanDefinition();
uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
uds.setFactoryMethodName("authenticationUserDetailsService");
uds.getConstructorArgumentValues().addGenericArgumentValue(x509Elt.getAttribute(ATT_USER_SERVICE_REF));
provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", uds);
this.x509ProviderRef = new RuntimeBeanReference(this.pc.getReaderContext().registerWithGeneratedName(provider));
}
private void createPrauthEntryPoint(Element source) {
if (this.preAuthEntryPoint == null) {
this.preAuthEntryPoint = new RootBeanDefinition(Http403ForbiddenEntryPoint.class);
this.preAuthEntryPoint.setSource(this.pc.extractSource(source));
}
}
void createJeeFilter(BeanReference authManager,
BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
Element jeeElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.JEE);
RootBeanDefinition filter = null;
if (jeeElt != null) {
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder
.rootBeanDefinition(J2eePreAuthenticatedProcessingFilter.class);
filterBuilder.getRawBeanDefinition().setSource(this.pc.extractSource(jeeElt));
filterBuilder.addPropertyValue("authenticationManager", authManager);
filterBuilder.addPropertyValue("securityContextHolderStrategy",
authenticationFilterSecurityContextHolderStrategyRef);
BeanDefinitionBuilder adsBldr = BeanDefinitionBuilder
.rootBeanDefinition(J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.class);
adsBldr.addPropertyValue("userRoles2GrantedAuthoritiesMapper",
new RootBeanDefinition(SimpleAttributes2GrantedAuthoritiesMapper.class));
String roles = jeeElt.getAttribute(ATT_MAPPABLE_ROLES);
Assert.hasLength(roles, "roles is expected to have length");
BeanDefinitionBuilder rolesBuilder = BeanDefinitionBuilder.rootBeanDefinition(StringUtils.class);
rolesBuilder.addConstructorArgValue(roles);
rolesBuilder.setFactoryMethod("commaDelimitedListToSet");
RootBeanDefinition mappableRolesRetriever = new RootBeanDefinition(SimpleMappableAttributesRetriever.class);
mappableRolesRetriever.getPropertyValues()
.addPropertyValue("mappableAttributes", rolesBuilder.getBeanDefinition());
adsBldr.addPropertyValue("mappableRolesRetriever", mappableRolesRetriever);
filterBuilder.addPropertyValue("authenticationDetailsSource", adsBldr.getBeanDefinition());
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
createPrauthEntryPoint(jeeElt);
createJeeProvider();
}
this.jeeFilter = filter;
}
private void createJeeProvider() {
Element jeeElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.JEE);
BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
RootBeanDefinition uds;
if (StringUtils.hasText(jeeElt.getAttribute(ATT_USER_SERVICE_REF))) {
uds = new RootBeanDefinition();
uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
uds.setFactoryMethodName("authenticationUserDetailsService");
uds.getConstructorArgumentValues().addGenericArgumentValue(jeeElt.getAttribute(ATT_USER_SERVICE_REF));
}
else {
uds = new RootBeanDefinition(PreAuthenticatedGrantedAuthoritiesUserDetailsService.class);
}
provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", uds);
this.jeeProviderRef = new RuntimeBeanReference(this.pc.getReaderContext().registerWithGeneratedName(provider));
}
void createLoginPageFilterIfNeeded() {
boolean needLoginPage = this.formFilterId != null || this.oauth2LoginFilterId != null;
// If no login page has been defined, add in the default page generator.
if (needLoginPage && this.formLoginPage == null) {
this.logger.info("No login page configured. The default internal one will be used. Use the '"
+ FormLoginBeanDefinitionParser.ATT_LOGIN_PAGE + "' attribute to set the URL of the login page.");
BeanDefinitionBuilder loginPageFilter = BeanDefinitionBuilder
.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
loginPageFilter.addPropertyValue("resolveHiddenInputs", new CsrfTokenHiddenInputFunction());
BeanDefinitionBuilder logoutPageFilter = BeanDefinitionBuilder
.rootBeanDefinition(DefaultLogoutPageGeneratingFilter.class);
logoutPageFilter.addPropertyValue("resolveHiddenInputs", new CsrfTokenHiddenInputFunction());
if (this.formFilterId != null) {
loginPageFilter.addConstructorArgReference(this.formFilterId);
loginPageFilter.addPropertyValue("authenticationUrl", this.loginProcessingUrl);
}
if (this.oauth2LoginFilterId != null) {
loginPageFilter.addPropertyValue("Oauth2LoginEnabled", true);
loginPageFilter.addPropertyValue("Oauth2AuthenticationUrlToClientName", this.oauth2LoginLinks);
}
if (this.saml2AuthenticationFilterId != null) {
loginPageFilter.addPropertyValue("saml2LoginEnabled", true);
loginPageFilter.addPropertyValue("saml2AuthenticationUrlToProviderName",
this.saml2AuthenticationUrlToProviderName);
}
this.loginPageGenerationFilter = loginPageFilter.getBeanDefinition();
this.logoutPageGenerationFilter = logoutPageFilter.getBeanDefinition();
this.defaultResourcesFilter = BeanDefinitionBuilder.rootBeanDefinition(DefaultResourcesFilter.class)
.setFactoryMethod("css")
.getBeanDefinition();
}
}
void createLogoutFilter(BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
Element logoutElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.LOGOUT);
if (logoutElt != null || this.autoConfig) {
String formLoginPage = this.formLoginPage;
if (formLoginPage == null) {
formLoginPage = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL;
}
LogoutBeanDefinitionParser logoutParser = new LogoutBeanDefinitionParser(formLoginPage,
this.rememberMeServicesId, this.csrfLogoutHandler,
authenticationFilterSecurityContextHolderStrategyRef);
this.logoutFilter = logoutParser.parse(logoutElt, this.pc);
this.logoutHandlers = logoutParser.getLogoutHandlers();
this.logoutSuccessHandler = logoutParser.getLogoutSuccessHandler();
}
}
private void createSaml2LogoutFilter(BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
Element saml2LogoutElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.SAML2_LOGOUT);
if (saml2LogoutElt == null) {
return;
}
Saml2LogoutBeanDefinitionParser parser = new Saml2LogoutBeanDefinitionParser(this.logoutHandlers,
this.logoutSuccessHandler, authenticationFilterSecurityContextHolderStrategyRef);
parser.parse(saml2LogoutElt, this.pc);
BeanDefinition saml2LogoutFilter = parser.getLogoutFilter();
BeanDefinition saml2LogoutRequestFilter = parser.getLogoutRequestFilter();
BeanDefinition saml2LogoutResponseFilter = parser.getLogoutResponseFilter();
this.saml2LogoutFilterId = this.pc.getReaderContext().generateBeanName(saml2LogoutFilter);
this.saml2LogoutRequestFilterId = this.pc.getReaderContext().generateBeanName(saml2LogoutRequestFilter);
this.saml2LogoutResponseFilterId = this.pc.getReaderContext().generateBeanName(saml2LogoutResponseFilter);
// register the component
this.pc.registerBeanComponent(new BeanComponentDefinition(saml2LogoutFilter, this.saml2LogoutFilterId));
this.pc.registerBeanComponent(
new BeanComponentDefinition(saml2LogoutRequestFilter, this.saml2LogoutRequestFilterId));
this.pc.registerBeanComponent(
new BeanComponentDefinition(saml2LogoutResponseFilter, this.saml2LogoutResponseFilterId));
}
@SuppressWarnings({ "rawtypes", "unchecked" })
ManagedList getLogoutHandlers() {
if (this.logoutHandlers == null && this.rememberMeProviderRef != null) {
this.logoutHandlers = new ManagedList();
if (this.csrfLogoutHandler != null) {
this.logoutHandlers.add(this.csrfLogoutHandler);
}
this.logoutHandlers.add(new RuntimeBeanReference(this.rememberMeServicesId));
this.logoutHandlers.add(new RootBeanDefinition(SecurityContextLogoutHandler.class));
}
return this.logoutHandlers;
}
BeanMetadataElement getEntryPointBean() {
return this.mainEntryPoint;
}
BeanMetadataElement getAccessDeniedHandlerBean() {
return this.accessDeniedHandler;
}
List<BeanDefinition> getCsrfIgnoreRequestMatchers() {
return this.csrfIgnoreRequestMatchers;
}
void createAnonymousFilter(BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
Element anonymousElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.ANONYMOUS);
if (anonymousElt != null && "false".equals(anonymousElt.getAttribute("enabled"))) {
return;
}
String grantedAuthority = null;
String username = null;
String key = null;
Object source = this.pc.extractSource(this.httpElt);
if (anonymousElt != null) {
grantedAuthority = anonymousElt.getAttribute("granted-authority");
username = anonymousElt.getAttribute("username");
key = anonymousElt.getAttribute(ATT_KEY);
source = this.pc.extractSource(anonymousElt);
}
if (!StringUtils.hasText(grantedAuthority)) {
grantedAuthority = "ROLE_ANONYMOUS";
}
if (!StringUtils.hasText(username)) {
username = "anonymousUser";
}
if (!StringUtils.hasText(key)) {
// Generate a random key for the Anonymous provider
key = createKey();
}
this.anonymousFilter = new RootBeanDefinition(AnonymousAuthenticationFilter.class);
this.anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(0, key);
this.anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(1, username);
this.anonymousFilter.getConstructorArgumentValues()
.addIndexedArgumentValue(2, AuthorityUtils.commaSeparatedStringToAuthorityList(grantedAuthority));
this.anonymousFilter.getPropertyValues()
.addPropertyValue("securityContextHolderStrategy", authenticationFilterSecurityContextHolderStrategyRef);
this.anonymousFilter.setSource(source);
RootBeanDefinition anonymousProviderBean = new RootBeanDefinition(AnonymousAuthenticationProvider.class);
anonymousProviderBean.getConstructorArgumentValues().addIndexedArgumentValue(0, key);
anonymousProviderBean.setSource(this.anonymousFilter.getSource());
String id = this.pc.getReaderContext().generateBeanName(anonymousProviderBean);
this.pc.registerBeanComponent(new BeanComponentDefinition(anonymousProviderBean, id));
this.anonymousProviderRef = new RuntimeBeanReference(id);
}
private String createKey() {
SecureRandom random = new SecureRandom();
return Long.toString(random.nextLong());
}
void createExceptionTranslationFilter(BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef) {
BeanDefinitionBuilder etfBuilder = BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
this.accessDeniedHandler = createAccessDeniedHandler(this.httpElt, this.pc);
etfBuilder.addPropertyValue("accessDeniedHandler", this.accessDeniedHandler);
Assert.state(this.requestCache != null, "No request cache found");
this.mainEntryPoint = selectEntryPoint();
etfBuilder.addConstructorArgValue(this.mainEntryPoint);
etfBuilder.addConstructorArgValue(this.requestCache);
etfBuilder.addPropertyValue("securityContextHolderStrategy",
authenticationFilterSecurityContextHolderStrategyRef);
this.etf = etfBuilder.getBeanDefinition();
}
private BeanMetadataElement createAccessDeniedHandler(Element element, ParserContext pc) {
Element accessDeniedElt = DomUtils.getChildElementByTagName(element, Elements.ACCESS_DENIED_HANDLER);
BeanDefinitionBuilder accessDeniedHandler = BeanDefinitionBuilder
.rootBeanDefinition(AccessDeniedHandlerImpl.class);
if (accessDeniedElt != null) {
String errorPage = accessDeniedElt.getAttribute("error-page");
String ref = accessDeniedElt.getAttribute("ref");
if (StringUtils.hasText(errorPage)) {
if (StringUtils.hasText(ref)) {
pc.getReaderContext()
.error("The attribute " + ATT_ACCESS_DENIED_ERROR_PAGE
+ " cannot be used together with the 'ref' attribute within <"
+ Elements.ACCESS_DENIED_HANDLER + ">", pc.extractSource(accessDeniedElt));
}
accessDeniedHandler.addPropertyValue("errorPage", errorPage);
return accessDeniedHandler.getBeanDefinition();
}
if (StringUtils.hasText(ref)) {
return new RuntimeBeanReference(ref);
}
}
if (this.defaultDeniedHandlerMappings.isEmpty()) {
return accessDeniedHandler.getBeanDefinition();
}
if (this.defaultDeniedHandlerMappings.size() == 1) {
return this.defaultDeniedHandlerMappings.values().iterator().next();
}
accessDeniedHandler = BeanDefinitionBuilder
.rootBeanDefinition(RequestMatcherDelegatingAccessDeniedHandler.class);
accessDeniedHandler.addConstructorArgValue(this.defaultDeniedHandlerMappings);
accessDeniedHandler
.addConstructorArgValue(BeanDefinitionBuilder.rootBeanDefinition(AccessDeniedHandlerImpl.class));
return accessDeniedHandler.getBeanDefinition();
}
private BeanMetadataElement selectEntryPoint() {
// We need to establish the main entry point.
// First check if a custom entry point bean is set
String customEntryPoint = this.httpElt.getAttribute(ATT_ENTRY_POINT_REF);
if (StringUtils.hasText(customEntryPoint)) {
return new RuntimeBeanReference(customEntryPoint);
}
if (!this.defaultEntryPointMappings.isEmpty()) {
if (this.defaultEntryPointMappings.size() == 1) {
return this.defaultEntryPointMappings.values().iterator().next();
}
BeanDefinitionBuilder delegatingEntryPoint = BeanDefinitionBuilder
.rootBeanDefinition(DelegatingAuthenticationEntryPoint.class);
delegatingEntryPoint.addConstructorArgValue(this.defaultEntryPointMappings);
return delegatingEntryPoint.getBeanDefinition();
}
Element basicAuthElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.BASIC_AUTH);
Element formLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.FORM_LOGIN);
// Basic takes precedence if explicit element is used and no others are configured
if (basicAuthElt != null && formLoginElt == null && this.oauth2LoginEntryPoint == null) {
return this.basicEntryPoint;
}
if (this.formFilterId != null) {
// If form login was enabled through element and Oauth2 login was enabled from
// element then use form login (gh-6802)
if (formLoginElt != null && this.oauth2LoginEntryPoint != null) {
return this.formEntryPoint;
}
// If form login was enabled through auto-config, and Oauth2 login & Saml2
// login was not
// enabled then use form login
if (this.oauth2LoginEntryPoint == null) {
return this.formEntryPoint;
}
}
// If X.509 or JEE have been enabled, use the preauth entry point.
if (this.preAuthEntryPoint != null) {
return this.preAuthEntryPoint;
}
// OAuth2 entry point will not be null if only 1 client registration
if (this.oauth2LoginEntryPoint != null) {
return this.oauth2LoginEntryPoint;
}
this.pc.getReaderContext()
.error("No AuthenticationEntryPoint could be established. Please "
+ "make sure you have a login mechanism configured through the namespace (such as form-login) or "
+ "specify a custom AuthenticationEntryPoint with the '" + ATT_ENTRY_POINT_REF + "' attribute ",
this.pc.extractSource(this.httpElt));
return null;
}
private void createUserDetailsServiceFactory() {
if (this.pc.getRegistry().containsBeanDefinition(BeanIds.USER_DETAILS_SERVICE_FACTORY)) {
// Multiple <http> case
return;
}
RootBeanDefinition bean = new RootBeanDefinition(UserDetailsServiceFactoryBean.class);
bean.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
this.pc.registerBeanComponent(new BeanComponentDefinition(bean, BeanIds.USER_DETAILS_SERVICE_FACTORY));
}
List<OrderDecorator> getFilters() {
List<OrderDecorator> filters = new ArrayList<>();
if (this.anonymousFilter != null) {
filters.add(new OrderDecorator(this.anonymousFilter, SecurityFilters.ANONYMOUS_FILTER));
}
if (this.rememberMeFilter != null) {
filters.add(new OrderDecorator(this.rememberMeFilter, SecurityFilters.REMEMBER_ME_FILTER));
}
if (this.logoutFilter != null) {
filters.add(new OrderDecorator(this.logoutFilter, SecurityFilters.LOGOUT_FILTER));
}
if (this.x509Filter != null) {
filters.add(new OrderDecorator(this.x509Filter, SecurityFilters.X509_FILTER));
}
if (this.jeeFilter != null) {
filters.add(new OrderDecorator(this.jeeFilter, SecurityFilters.PRE_AUTH_FILTER));
}
if (this.formFilterId != null) {
filters.add(
new OrderDecorator(new RuntimeBeanReference(this.formFilterId), SecurityFilters.FORM_LOGIN_FILTER));
}
if (this.oauth2LoginFilterId != null) {
filters.add(new OrderDecorator(new RuntimeBeanReference(this.oauth2LoginFilterId),
SecurityFilters.OAUTH2_LOGIN_FILTER));
filters.add(new OrderDecorator(this.oauth2AuthorizationRequestRedirectFilter,
SecurityFilters.OAUTH2_AUTHORIZATION_REQUEST_FILTER));
}
if (this.loginPageGenerationFilter != null) {
filters.add(new OrderDecorator(this.loginPageGenerationFilter, SecurityFilters.LOGIN_PAGE_FILTER));
filters.add(new OrderDecorator(this.logoutPageGenerationFilter, SecurityFilters.LOGOUT_PAGE_FILTER));
}
if (this.defaultResourcesFilter != null) {
filters.add(new OrderDecorator(this.defaultResourcesFilter, SecurityFilters.DEFAULT_RESOURCES_FILTER));
}
if (this.basicFilter != null) {
filters.add(new OrderDecorator(this.basicFilter, SecurityFilters.BASIC_AUTH_FILTER));
}
if (this.bearerTokenAuthenticationFilter != null) {
filters.add(
new OrderDecorator(this.bearerTokenAuthenticationFilter, SecurityFilters.BEARER_TOKEN_AUTH_FILTER));
}
if (this.authorizationCodeGrantFilter != null) {
filters.add(new OrderDecorator(this.authorizationRequestRedirectFilter,
SecurityFilters.OAUTH2_AUTHORIZATION_REQUEST_FILTER.getOrder() + 1));
filters.add(new OrderDecorator(this.authorizationCodeGrantFilter,
SecurityFilters.OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER));
}
if (this.saml2AuthenticationFilterId != null) {
filters.add(new OrderDecorator(new RuntimeBeanReference(this.saml2AuthenticationFilterId),
SecurityFilters.SAML2_AUTHENTICATION_FILTER));
filters.add(new OrderDecorator(new RuntimeBeanReference(this.saml2AuthenticationRequestFilterId),
SecurityFilters.SAML2_AUTHENTICATION_REQUEST_FILTER));
}
if (this.saml2LogoutFilterId != null) {
filters.add(new OrderDecorator(new RuntimeBeanReference(this.saml2LogoutFilterId),
SecurityFilters.SAML2_LOGOUT_FILTER));
filters.add(new OrderDecorator(new RuntimeBeanReference(this.saml2LogoutRequestFilterId),
SecurityFilters.SAML2_LOGOUT_REQUEST_FILTER));
filters.add(new OrderDecorator(new RuntimeBeanReference(this.saml2LogoutResponseFilterId),
SecurityFilters.SAML2_LOGOUT_RESPONSE_FILTER));
}
filters.add(new OrderDecorator(this.etf, SecurityFilters.EXCEPTION_TRANSLATION_FILTER));
return filters;
}
List<BeanReference> getProviders() {
List<BeanReference> providers = new ArrayList<>();
if (this.anonymousProviderRef != null) {
providers.add(this.anonymousProviderRef);
}
if (this.rememberMeProviderRef != null) {
providers.add(this.rememberMeProviderRef);
}
if (this.x509ProviderRef != null) {
providers.add(this.x509ProviderRef);
}
if (this.jeeProviderRef != null) {
providers.add(this.jeeProviderRef);
}
if (this.oauth2LoginAuthenticationProviderRef != null) {
providers.add(this.oauth2LoginAuthenticationProviderRef);
}
if (this.oauth2LoginOidcAuthenticationProviderRef != null) {
providers.add(this.oauth2LoginOidcAuthenticationProviderRef);
}
if (this.authorizationCodeAuthenticationProviderRef != null) {
providers.add(this.authorizationCodeAuthenticationProviderRef);
}
providers.addAll(this.authenticationProviders);
return providers;
}
private static class CsrfTokenHiddenInputFunction implements Function<HttpServletRequest, Map<String, String>> {
@Override
public Map<String, String> apply(HttpServletRequest request) {
CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (token == null) {
return Collections.emptyMap();
}
return Collections.singletonMap(token.getParameterName(), token.getToken());
}
}
}