Announcement Announcement Module
Collapse
No announcement yet.
Spring Security Pre-authentication without authorization Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring Security Pre-authentication without authorization

    I am trying to implement pre-authentication scenario and I am running into few issues.. This is my security context file..

    Code:
    <sec:global-method-security secured-annotations="enabled" pre-post-annotations="disabled"/>
    <sec:http pattern="/static/**" security="none" />
    <bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
        <property name="preAuthenticatedUserDetailsService">
            <bean id="userDetailsServiceWrapper"
                class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
                    <property name="userDetailsService" ref="userDetailsService"/>
            </bean>
        </property>
    </bean>
    
    <bean id="userDetailsService"
        class="com.myapp.UserDetailsServiceImpl"/>
    
    <sec:authentication-manager alias="authenticationManager">
      <sec:authentication-provider ref="preauthAuthProvider" />
    </sec:authentication-manager>
    
    <sec:http auto-config="false" use-expressions="true">
        <sec:intercept-url pattern="/index.htm" access="permitAll"/>
        <sec:intercept-url pattern="/logoff.html" access="permitAll"/>
        <sec:intercept-url pattern="/profile/**" access="hasAnyRole('ROLE_PROFILEUSER', 'ROLE_ADMIN')"/>
        <sec:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
        <sec:intercept-url pattern="/**" access="isAuthenticated()"/>
        <!-- <sec:form-login login-page="/login.html"  default-target-url="/home.html" authentication-failure-url="/login.html"/> -->
        <sec:logout logout-url="/logoff.html"/> 
        <sec:custom-filter position="PRE_AUTH_FILTER" ref="channelSecureFilter" />
    </sec:http>
    
    <bean id="channelSecureFilter"
        class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
    
        <property name="principalRequestHeader" value="SM_UNIVERSAL_ID"/>   
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="invalidateSessionOnPrincipalChange" value="true"/>
    </bean>
    
    
    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
        <property name="decisionVoters">
            <list>
                <ref local="roleVoter"/>
                <ref local="authenticatedVoter"/>
            </list>
        </property>
    
    </bean>
    
    <bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter">
        <property name="rolePrefix" value="ROLE_"/>
    </bean>
    
    <bean id="authenticatedVoter" class="org.springframework.security.access.vote.AuthenticatedVoter"/>
    and this is the custom UserDetailsServiceImpl

    Code:
    @Component
    public class UserDetailsServiceImpl extends PreAuthenticatedGrantedAuthoritiesUserDetailsService implements UserDetailsService{
       @Autowired PersonService personService;
    
    
    @Override
    public UserDetails loadUserByUsername(String arg0) throws UsernameNotFoundException {
               //I dont think anything is needed here... right?
        return null;
    }
    
    @Override
    protected UserDetails createuserDetails(Authentication token,
            Collection<? extends GrantedAuthority> role){
    
        Person lp = PersonService.findPersonByNetId(token.getName());
    
        PreAuthenticatedGrantedAuthoritiesUserDetailsService test = new PreAuthenticatedGrantedAuthoritiesUserDetailsService();
    
    
        if(lp==null){
            role.add(new SimpleGrantedAuthority("ROLE_USER"));
            return new LLUser(token.getName(),"N/A", true, true, true, true, role, null);
        }
        else{
            boolean enabled = (lp.getIsActive()==1)?true:false;
            boolean credentialsNonExpired = (lp.getIsActive()==1)?true:false;
            //test whehther deactivate date is null or deactivate data is greater than current date
            boolean accountNonExpired = ((lp.getDeactivateDate()==null)||(lp.getDeactivateDate().compareTo(new Date())>0))?true:false;
            boolean accountNonLocked = (lp.getIsActive()==1)?true:false;
            Integer personId = lp.getPerson().getId();
    
            if(lp.getLlRole()!=null){
                if(lp.getLlRole()==10)
                {   
                    role.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
                    role.add(new SimpleGrantedAuthority("ROLE_PROFILEUSER"));
                }
                if(lp.getLlRole()==25)
                    role.add(new SimpleGrantedAuthority("ROLE_PROFILEUSER"));
                }
    
            role.add(new SimpleGrantedAuthority("ROLE_USER"));
    
            return new LLUser(token.getName(),"N/A", enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, role, personId);
        }
    
    }
    }
    LLUser is a custom user object that extends Spring's user object. So, now the issues are,

    1). I cannot seem to add SimpleGrantedauthoriy to the "role" collection. I am getting following error and I can't understand it because SimplegGrantedAuthority is an implementation of GrantedAuthority right?

    PHP Code:
    the method add(capture#1-of ? extends GrantedAuthority) in the type collection<capture#1-of ? extends GrantedAuthority> is not applicable for the arguments (SimpleGrantedAuthority) 
    2). I am very sure my way of initializing the custom User object is incorrect because, there is no password coming from the request and User class will not know what to compare against?

    Also, please look at my context config file and let me know if there are any redundant elements or if I am missing anything important. Thanks in advance.

  • #2
    From the API docs, it looks like extending the PreAuthenticatedGrantedAuthoritiesUserDetailsServi ce is not proper way ti attach roles the principal.
    This AuthenticationUserDetailsService implementation creates a UserDetails object based solely on the information contained in the given PreAuthenticatedAuthenticationToken. The user name is set to the name as returned by PreAuthenticatedAuthenticationToken.getName(), the password is set to a fixed dummy value (it will not be used by the PreAuthenticatedAuthenticationProvider anyway), and the Granted Authorities are retrieved from the details object as returned by PreAuthenticatedAuthenticationToken.getDetails().
    Can anyone guide me on where exactly should I add roles?

    Comment


    • #3
      I have a similar problem. And that's what I did:

      1) I use a custom User with an empty password with a custom userDetailsService that builds a custom User (that extends the org.springframework.security.core.userdetails.User that implements UserDetails), and I use a custom daoAuthenticationProvider that manages the empty password (it extends DaoAuthenticationProvider and overrides the additionalAuthenticationChecks method by calling the super.method and swallowing the BadCredentialsException)

      I couldn't make it in a better way.

      In order to improve the security, I made a custom FilterInvocationSecurityMetadataSource that adds the IS_AUTHENTICATED_FULLY SecurityConfig to the ConfigAttributes of any secured object.

      2) I managed the empty password in the User as I said above. In order to let Spring Security to do the Authentication without password, I build a weird system based on Basic Authentication: http://forum.springsource.org/showthread.php?115869

      I accept any kind of comments because I'm not very happy with the result, but at least, it seems to work (for now )

      Comment


      • #4
        thanks for the reply jbbarquero.. your implementation seems to be the best possible for authenticating against db.. but it turns out I don't need that much complex stuff.. since I am using preauthentication filter, it doesn't matter what password I put in User object since it was already authenticated.. api docs clearly mention that.. if only I spent more time reading those

        Comment


        • #5
          I dont even need to extend PreAuthenticatedGrantedAuthroritiesUserDetailsServ ice class. I can just add the roles in loadUserByUsername(String userName) itself.. this is what I have now and it is working (for now :P)

          Code:
          public UserDetails loadUserByUsername(String netId) throws UsernameNotFoundException {
          	
          Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
          		
          		Person lp = personService.findPersonByNetId(netId);
          		
          		if(person==null){
          			authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
          			return new LLUser(netId, "N/A", true,true, true,true, authorities, null);
          		}
          			
          		
          		String userName = person.getNetId();
          		String password = person.getLastName();
          		boolean enabled = (person.getIsActive()==1)?true:false;
          		boolean credentialsNonExpired = (person.getIsActive()==1)?true:false;
          		//test whehther deactivate date is null or deactivate data is greater than current date
          		boolean accountNonExpired = ((person.getDeactivateDate()==null)||(person.getDeactivateDate().compareTo(new Date())>0))?true:false;
          		boolean accountNonLocked = (person.getIsActive()==1)?true:false;
          		
          		
          		
          		if(person.getLlRole()!=null){
          			if(person.getLlRole()==10)
          				authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
          			
          			authorities.add(new SimpleGrantedAuthority("ROLE_PROFILEUSER"));
          		}
          		
          		authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
          		
          		LLUser user = new LLUser(userName, password, enabled, accountNonExpired, credentialsNonExpired,accountNonLocked, authorities, person.getPerson().getId()); 
          				
          		return user;
          
          	}

          Comment

          Working...
          X