Skip to content

Every XML sec:authentication-manager creates a new global instance of AuthenticationEventPublisher #7282

Closed
@djechelon

Description

@djechelon

Summary

When you use multiple sec:authentication-managers, you can't @Autowire the AuthenticationEventPublisher because every sec:authentication-manager will instantiate its own public bean

Detailed explanation

I work on a plugin-based authentication architecture. All plugins must be switched by Spring profiles and should coexist if possible (all active have no effect).

Currently I have two kinds of plugins:

  • SSO plugins have their own filter and a dedicated authentication manager, e.g.
  • For username-password-based plugins (e.g. Active Directory, database, custom lookup) I had to invent an ExtensibleAuthenticationManager that basically wraps a ProviderManager and scans for AuthenticationProviders that support UsernamePasswordToken
public class ExtensibleAuthenticationManager implements AuthenticationManager, InitializingBean
{
    private final static Logger log = LogManager.getLogger();

    private AuthenticationManager parentAuthenticationManager;
    private ProviderManager providerManager;
    private Class<? extends Authentication> limitToClass;

    @Autowired
    private ListableBeanFactory beanFactory;
    @Autowired
    private MessageSource messageSource;
    @Autowired(required = false)
    private AuthenticationEventPublisher authenticationEventPublisher;

Actual Behavior

Reference

Since Spring Security creates a globally-visible bean of type DefaultAuthenticationEventPublisher every time it creates an authentication manager, you can autowire it

Expected Behavior

There should be either one globally-visible bean of type AuthenticationEventPublisher that can be autowired in other beans if required, or the definition of a new AuthenticationManager should inject an instance of DefaultAuthenticationEventPublisher that is private to the authentication manager.

I would prefer the latter, because if one writes their own security plugin there will be actually no public AuthenticationEventPublisher to Autowire, and developer is forced to find their own way (i.e. declare explicitly) to autowire into their authenticatio components

Configuration

<beans profile="CEDACRISEC" xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sec="http://www.springframework.org/schema/security"
       xsi:schemaLocation="http://www.springframework.org/schema/beans     http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                           http://www.springframework.org/schema/security  http://www.springframework.org/schema/security/spring-security-4.2.xsd"
>
    <sec:authentication-manager id="cedacriAuthenticationManager">
        <sec:authentication-provider ref="cedacriAuthenticationProvider"/>
    </sec:authentication-manager>

    <bean id="formLoginFilter_cedacri" class="it.phoenix.web.security.cedacri.CedacriAuthenticationFilter">


---------------------------


<beans profile="ICCREASEC"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                        http://www.springframework.org/schema/security
                        http://www.springframework.org/schema/security/spring-security-4.2.xsd">

    <bean id="preAuthFilter_iccrea" class="it.phoenix.web.security.spring.PreAuthenticatedIccreaProcessingFilter">
        <property name="sessionAuthenticationStrategy"
                  ref="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy#0"/>
        <property name="authenticationManager" ref="iccreaAuthenticationManager"/>
        <property name="authenticationSuccessHandler" ref="authenticationHandler"/>
        <property name="authenticationFailureHandler" ref="authenticationHandler"/>
    </bean>

    <sec:authentication-manager id="iccreaAuthenticationManager">
        <sec:authentication-provider ref="iccreaPreAuthProvider"/>
    </sec:authentication-manager>

---------------------------

<beans profile="PREAUTHSEC" xmlns:sec="http://www.springframework.org/schema/security" xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                        http://www.springframework.org/schema/security
                        http://www.springframework.org/schema/security/spring-security-4.2.xsd"
>

    <bean id="preAuthFilter_preauthsec" class="it.phoenix.web.security.spring.PreAuthenticatedProcessingFilter">
        <property name="sessionAuthenticationStrategy"
                  ref="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy#0"/>
        <property name="authenticationFailureHandler" ref="authenticationHandler" />
        <property name="authenticationSuccessHandler" ref="authenticationHandler" />
        <property name="authenticationManager" ref="preauthAuthenticationManager"/>
        <property name="principalRequestHeader" value="${httpheader.preauth.user:SM_USER}"/>
        <property name="rolesRequestHeader" value="${httpheader.preauth.role:SM_ROLES}"/>
        <property name="rolesDelimiter" value="${httpheader.preauth.rolesDelimiter:,}"/>
    </bean>

    <sec:authentication-manager id="preauthAuthenticationManager">
        <sec:authentication-provider ref="profilesAuthenticationProvider"/>
    </sec:authentication-manager>

</beans>

---------------------------

<sec:http name="httpSecurityContext" auto-config="false" use-expressions="true" access-decision-manager-ref="accessDecisionManager"
              authentication-manager-ref="usernamePasswordAuthenticationManager"
              entry-point-ref="authenticationEntryPoint"
    >
   .............

    <bean id="usernamePasswordAuthenticationManager" class="it.phoenix.web.security.spring.ExtensibleAuthenticationManager" lazy-init="true">
        <property name="limitToClass" value="org.springframework.security.authentication.UsernamePasswordAuthenticationToken" />
    </bean>
</sec:http>


Version

Using version 4.2.11 but should affect all 4.2.x

Related

#4400
#4269

Metadata

Metadata

Assignees

Labels

in: configAn issue in spring-security-configstatus: backportedAn issue that has been backported to maintenance branchesstatus: ideal-for-contributionAn issue that we actively are looking for someone to help us withtype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions