Page 1 of 2 12 LastLast
Results 1 to 10 of 16

Thread: Custom Authentication Provider and User Details

  1. #1

    Default Custom Authentication Provider and User Details

    I have a custom Authentication Provider working in my app. How do I setup the config to use a custom UserDetails Object with the custom Authentication Provider?
    Here is the config for the custom Authentication Provider:

    Code:
    <bean id="customAuthenticationProvider" class="app.security.CustomAuthenticationProvider">
    <security:custom-authentication-provider/>
    </bean>

  2. #2
    Luke Taylor is offline Senior Member Acegi Security System TeamSpring Team
    Join Date
    Aug 2004
    Location
    Glasgow, Scotland
    Posts
    3,449

    Default

    You'll have to explain what you mean by "use a custom UserDetails object". The UserDetails would normally be loaded somewhere inside your class "CustomAuthenticationProvider", so it's up to you how you do that.

  3. #3

    Default

    I want to store additional information for the authenticated user and I have read that to do this you need to create a custom UserDetails object that implements UserDetails. How do I access it in the CustomAuthenticationProvider?

    Code:
    public class CustomAuthenticationProvider implements AuthenticationProvider {
    
    @Resource DataSource dataSource;
    
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String username = String.valueOf(auth.getPrincipal());
    //use the username to retrieve additional user data from database and store in Spring's User object - my custom User Details object

  4. #4
    Join Date
    Nov 2008
    Location
    Swansea, Wales
    Posts
    204

    Default

    I have a custom authentication provider and all I did was implement org.springframework.security.userdetails.UserDetai lsService and override the loadUserByUsername method. It is declared in the config simply as

    Code:
    <security:authentication-provider
    		user-service-ref="userDetailsService" />
    The loadUserByUsername must return a org.springframework.security.userdetails.UserDetai ls object and I return a custom object that extends that abstract class and provides the additional properties I need

    Code:
    package demo.service.impl.user;
    
    import javax.persistence.NoResultException;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.dao.DataAccessException;
    import org.springframework.security.userdetails.UserDetails;
    import org.springframework.security.userdetails.UserDetailsService;
    import org.springframework.security.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import demo.domain.aggregates.user.User;
    import demo.domain.applicationservice.UserApplicationService;
    
    @Service("userDetailsService")
    public class UserDetailsServiceImpl implements UserDetailsService {
    
      @Autowired
      private UserApplicationService userApplicationService;
    
      @Autowired
      private UserServiceAssembler assembler;
    
      @Transactional(readOnly = true)
      public UserDetails loadUserByUsername(String username)
          throws UsernameNotFoundException, DataAccessException {
        try {
          User user = userApplicationService.findUserByUsername(username);
          return assembler.buildAuthenticatedUserDTOFromUser(user);
        } catch (NoResultException e) {
          throw new UsernameNotFoundException(e.getLocalizedMessage());
        }
      }
    }
    Code:
    package demo.service.api.user.dto;
    
    import org.springframework.security.GrantedAuthority;
    import org.springframework.security.userdetails.User;
    
    public class AuthenticatedUserDto extends User {
    
      private static final long serialVersionUID = 1L;
    
      private String displayName;
    
      private Integer userId;
    
      public String getDisplayName() {
        return displayName;
      }
    
      public Integer getUserId() {
        return userId;
      }
    
      public AuthenticatedUserDto(String username, String password,
          boolean enabled, boolean accountNonExpired,
          boolean credentialsNonExpired, boolean accountNonLocked,
          GrantedAuthority[] authorities, String displayName, Integer userId)
          throws IllegalArgumentException {
        super(username, password, enabled, accountNonExpired,
            credentialsNonExpired, accountNonLocked, authorities);
        this.displayName = displayName;
        this.userId = userId;
      }
    }

  5. #5

    Default

    I am using Spring Security 2.0.3 and I tried to add userDetailsService to my xml file.
    Code:
    <bean id="customAuthenticationProvider" class="app.security.CustomAuthenticationProvider">
    <security:custom-authentication-provider/>
    </bean>
    
    <security:authentication-provider
    		user-service-ref="userDetailsService" />
    I implemented org.springframework.security.userdetails.UserDetai lsService like the example code above and I added a print statement but it never gets into the userDetailsService. My custom authentication Provider is the only thing processed after the user enters his credentials. All I want to do is store a user id with the user object.
    Any help is greatly appreciated.

  6. #6
    Luke Taylor is offline Senior Member Acegi Security System TeamSpring Team
    Join Date
    Aug 2004
    Location
    Glasgow, Scotland
    Posts
    3,449

    Default

    If your custom provider handles the authentication request, then additional ones won't be queried.
    Spring - by Pivotal
    twitter @tekul

  7. #7

    Default

    Yes my custom provider handles the authentication request. So is there another way to store the user id with the User object?

  8. #8
    Join Date
    Nov 2008
    Location
    Swansea, Wales
    Posts
    204

    Default

    If you choose to implement UserDetailsService then you dont need a custom provider as well. Have you tried removing your customAuthenticationProvider config?

    What is the rest of your security config file?

  9. #9

    Default

    Security file config:
    Code:
    <security:http>
    <security:intercept-url pattern="/*" access="ROLE_USER"/>
    <security:form-login login-page="/spring/login" login-processing-url="/spring/loginProcess" default-target-url="/spring/main" authentication-failuer-url="="/spring/login?login_error=1"/>
    <security:logout logout-url="spring/logout" logout-success-url="/spring/logoutSuccess"/>
    </security:http>
    
    <bean id="customAuthenticationProvider" class="app.security.CustomAuthenticationProvider">
    <security:custom-authentication-provider/>
    </bean>
    I created the Custom Authentication Provider because I use the user's credentials to connect to an Oracle database for authentication. If the connection fails, I convert the sql error message to a user friendly message such as "Account is locked", "Password has expired", "Bad Credentials", etc.

  10. #10
    Join Date
    Nov 2008
    Location
    Swansea, Wales
    Posts
    204

    Default

    If you replace your customAuthenticationProvider with the userDetailsService implementation then you get all this functionality for free.

    My config file looks like this

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:security="http://www.springframework.org/schema/security"
    	xsi:schemaLocation="
               http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
               http://www.springframework.org/schema/security
               http://www.springframework.org/schema/security/spring-security-2.0.xsd">
    
    	<!-- Configure Spring Security -->
    	<security:http auto-config="true">
    		<security:intercept-url pattern="/capp/flow/*"
    			access="ROLE_SYS_USER" />
    		<security:form-login login-page="/capp/login"
    			login-processing-url="/capp/loginProcess"
    			default-target-url="/capp/flow/home?activeTabId=HOME"
    			authentication-failure-url="/capp/login?login_error=1" />
    		<security:logout logout-url="/capp/logout"
    			logout-success-url="/capp/login" />
    	</security:http>
    
    	<security:authentication-provider
    		user-service-ref="userDetailsService" />
    </beans>
    and on my login page I have the following section that displays a user friendly message

    Code:
    <c:if test="${not empty param.login_error}">
    				<div class="errors">
    					Your login attempt was not successful, try again.<br />
    					Reason: #{sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message}
    				</div>
    			</c:if>

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •