4
votes

I'm working on a web application that uses Spring Security 3.0.7 to authenticate users either by username/password or using OpenID. Now I need the ability to disable some accounts. At first I couldn't find a relevant documentation for, but finally I found out User.isEnabled():

Indicates whether the user is enabled or disabled. A disabled user cannot be authenticated.

the value for this flag is given in the constructor.

When authenticating using a form it seems to work fine. Unfortunately it seems that Spring's OpenID completely ignores the flag. I logged as much as I could and I can see in the log:

DEBUG o.s.s.o.OpenIDAuthenticationFilter - Authentication success. Updating SecurityContextHolder to contain: [org.springframework.security.openid.OpenIDAuthenticationToken@66348da1: Principal: mypackage.UserInfo@ddd49b1b: Username: cbada36792e42a3be5a5e0f77d14e918186c7e3f; Password: [PROTECTED]; Enabled: false; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffd148a: RemoteIpAddress: 127.0.0.1; SessionId: 1arhd8er0sj1yynglq8linpnb; Granted Authorities: ROLE_USER, attributes : []]

How can authentication be successful on a disabled account? (It is the same if I try to lock the account instead.)

Am I missing something important? Or is it just a bug? Any ideas what to look for, what more logging to enable?


My XML configuration:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
  xmlns="http://www.springframework.org/schema/security"
  xmlns:beans="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-3.0.xsd
  http://www.springframework.org/schema/security
  http://www.springframework.org/schema/security/spring-security-3.0.xsd">

  <global-method-security secured-annotations="enabled">
  </global-method-security>

  <http use-expressions="true" auto-config="true">
    <intercept-url pattern="/" access="permitAll" />
    <!-- ... other pattens -->
    <form-login
        login-page="/"
        authentication-success-handler-ref="loginSuccessHandler"
    />

    <remember-me data-source-ref="dataSource" user-service-ref="myUserDetails"/>

    <openid-login
        user-service-ref="openIdAuth"
        authentication-success-handler-ref="loginSuccessHandler"
        authentication-failure-handler-ref="openIdFailureHandler"
        >
      <attribute-exchange>
        <openid-attribute name="email" type="http://axschema.org/contact/email" required="true" />
        <openid-attribute name="name" type="http://axschema.org/namePerson" />
      </attribute-exchange>
    </openid-login>
    <logout success-handler-ref="logoutSuccessHandler"/>
  </http>

  <authentication-manager>
    <authentication-provider ref="daoAuthenticationProvider"/>
  </authentication-manager>

  <beans:bean id="daoAuthenticationProvider"
    class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <beans:property name="userDetailsService" ref="myUserDetails"/>
    <beans:property name="saltSource" ref="saltSource"/>
    <beans:property name="passwordEncoder" ref="passwordEncoder"/>
    <beans:property name="preAuthenticationChecks">
      <beans:bean class="org.springframework.security.authentication.AccountStatusUserDetailsChecker"/>
    </beans:property>
  </beans:bean>
</beans:beans>

Here myUserDetails is my custom bean that loads a user from a database and returns a simple custom implementation of User:

public class UserInfo
    extends User
{
    public UserInfo(UserEntity user)
    {
        super(  user.getUserName(),
                user.getPassword(),
                !user.isDisabled(), // enabled
                true, // non-expired
                true, // credentials non-expired
                !user.isLocked(), // non-locked
                UserInfo.authorities(user) // my static method
            );
        // store some info for further reference here
        // ...
    }
    // ...
}
1

1 Answers

0
votes

I'm dealing with similar situation right now.

Spring Security is based on filter chain. If you declare openid than opendId auth is added to Your security filter chain (I dont know spring openid details).

When your filter chain is on openId step and someone has logged in, than it will return auth success without watching into disable state in UserDetails table.

Chapter 7.3: docs.spring.io/spring-security/site/docs/3.0.x/reference/security-filter-chain.html

I use Spring Social (for FB etc.) and isDisabled() is not working for me too, when someone is login via FB.

Solution is to change default spring's openid implementation with your's, which watch on isDisabled() in UserDetails.

MAYBE here: OpenIDAuthenticationProvider. It's a shot! I don't know spring openid

Hope it help.