Question

Here is what I want to achieve:

I am using Websphere and I want to rely on the container to do the authentication (using Kerberos+SPNEGO). When it come to Spring Security, I want to rely on the pre-authentication, and use LDAP to retrieve user details (roles etc) for authorization checking.

Here is the part of Spring app context config I have (tried to only include related parts)

<s:global-method-security secured-annotations="enabled" pre-post-annotations="enabled" proxy-target-class="true" />

<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
    <s:filter-chain-map path-type="ant">
        <s:filter-chain pattern="/**"
            filters="securityContextPersistenceFilter,preAuthenticatedFilter" />
    </s:filter-chain-map>
</bean>


<s:http use-expressions="true" create-session="stateless" auto-config="true">
<!--
    <s:http-basic />
-->
</s:http>

<bean id="securityContextPersistenceFilter" 
        class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
    <property name='securityContextRepository'>
        <bean class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
            <property name='allowSessionCreation' value='true' />
        </bean>
    </property>
</bean>


<bean id="preAuthenticatedFilter"
        class="org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

<s:authentication-manager alias="authenticationManager">
    <s:authentication-provider ref="preAuthenticatedAuthenticationProvider"   />
</s:authentication-manager>

<bean id="preAuthenticatedAuthenticationProvider" 
        class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <property name="preAuthenticatedUserDetailsService" >
        <bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper" >
            <property name="userDetailsService" ref="userDetailsService" />
        </bean>
    </property>
</bean>


<bean id="userDetailsService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService" >
    <constructor-arg index="0" ref="ldapUserSearch"/>
    <constructor-arg index="1" ref="ldapAuthoritiesPopulator"/>
    <property name="userDetailsMapper" >
        <bean class="com.foo.MyUserDetailsMapper" />
    </property>
</bean>

<bean id="ldapContextSource"
    class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
    <!-- some setting skipped here -->
</bean>

<bean id="ldapUserSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    <!-- some setting skipped here -->
</bean>

<bean id="ldapAuthoritiesPopulator"
    class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
    <!-- some setting skipped here -->
</bean>

<bean id="ldapTemplate" class="org.springframework.ldap.core.simple.SimpleLdapTemplate">
    <constructor-arg ref="ldapContextSource" />
</bean>

It mostly worked, I can see correct user name and role coming in for my custom UserDetailsMapper (com.foo.MyUserDetailsMapper) which comes from LDAP, and inside that I am returning a new UserDetails with updated roles.

The problem is, in my controller, when I tried to do

SecurityContextHolder.getContext().getAuthentication()

It is returning null. (For which works before I change to pre-authentication)

Is there anything I missed?

Was it helpful?

Solution

Found the problem. Sorry that is mostly because of my own implementation fault which is not visible in the question itself.

My custom UserDetails impl is incorrectly having getEnabled() returning false. In LdapAuthenticationProvider, it is working fine as there is no checking on the user status.

However, in PreAuthenticatedAuthenticationProvider, by default there is a UserDetailsChecker which checks the status of user, for which getEnabled() returning false will cause the user details checker to fail silently, and causing authentication not populated to SecurityContext (i.e. treating that account as not authenticated)

Although it is mostly my implementation issue, I think still worth leaving here as a reference for difference of LdapAuthenticationProvider and PreAuthenticatedAuthenticationProvider

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top