Announcement Announcement Module
Collapse
No announcement yet.
Custom Authentication Provider and User Details Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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
    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.

    Comment


    • #3
      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

      Comment


      • #4
        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;
          }
        }

        Comment


        • #5
          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.

          Comment


          • #6
            If your custom provider handles the authentication request, then additional ones won't be queried.

            Comment


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

              Comment


              • #8
                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?

                Comment


                • #9
                  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.

                  Comment


                  • #10
                    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>

                    Comment


                    • #11
                      I am unable to paste my code in so there may be some typos.
                      CustomProviderAuthentication
                      Code:
                      public class CustomAuthenticationProvider implements AuthenticationProvider {
                      
                      @Resource DataSource dataSource;
                      
                      public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                      UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) authentication;
                      String username = String.valueOf(auth.getPrincipal());
                      String password = String.valueOf(auth.getCredentials());
                      Connection conn = null;
                      try{
                         //In this call I use the username and password and pass them to my oracle proxy connection and then try to    connect to the database 
                         conn = dataSourceAdapter.doGetConnection(username, password);
                      }
                      catch(SQLException sqle) {
                       throw new BadCredentialsException(LoginException.handleLoginErrors(sqle));
                      }
                      //I use the same connection to get the granted authorities, user's role and user's id
                      return new UsernamePasswordAuthenticationToken(username, password,new GrantedAuthority[] {new GrantedAuthorityImpl(userRole)});
                      }
                      It works well for testing the database connection.
                      Last edited by kmsheph; Dec 23rd, 2008, 05:21 AM.

                      Comment


                      • #12
                        Is it possible to post your userDetailsService related java implementation classes, please?

                        Thanks.
                        Last edited by mdebac; Dec 30th, 2008, 03:56 AM.

                        Comment


                        • #13
                          do you have implmentation for grants?

                          new GrantedAuthorityImpl(userRole)

                          Thanks.

                          Comment


                          • #14
                            Hi rhart,

                            as you mentioned in the code of class UserDetailsServiceImpl

                            Code:
                            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());
                                }
                              }
                            this method must return UserDetais object, I am not sure how can i do that....
                            Please help me as i am new to this.

                            Thanks in advance

                            Comment


                            • #15
                              modify the password

                              Is what possible to modify the password before the authentication.

                              Comment

                              Working...
                              X