Spring Security : Custom UserDetailsService and Custom UserDetails

Points To Remember

You need to change the UserDetailsService, User Object of the spring security to achieve this.

Add Custom User Details to Spring Security Authentication Object

First of all we nee to create a new User Object that will override the User class of the spring security in package org.springframework.security.core.userdetails.User After this, you need to tell  UserDetailsService to use this object as the principal for the authentication token. For this you will have to override the UserDetailsService of the spring security.

You can have the custom User object like.
Custom User Class -> MyUser.groovy
package com.ekiras

import org.springframework.security.core.GrantedAuthority

/**
 * Created by ekansh on 24/1/15.
 */
class MyUser extends org.springframework.security.core.userdetails.User {

    // Declare all custom attributes here
    private final Object id;
    private String name;

    public MyUser(String username, String password, boolean enabled, boolean accountNonExpired,
                      boolean credentialsNonExpired, boolean accountNonLocked,
                      Collection<GrantedAuthority> authorities, Object id, String name) {
        super(username, password, enabled, accountNonExpired, credentialsNonExpired,
                accountNonLocked, authorities);

        // Initialize all the custom attributes here like the following.
        this.id = id;
        this.name = name;
    }

    /**
     * Get the id.
     * @return the id
     */
    public Object getId() {
        return id;
    }
}

So now our User object will also contain a field name that is the concatenation of first name and last name.
Custom UserDertailService -> MyUserDetailsService.groovy
package com.ekiras

import grails.plugin.springsecurity.SpringSecurityUtils
import grails.plugin.springsecurity.userdetails.NoStackUsernameNotFoundException
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.core.userdetails.UsernameNotFoundException

/**
 * Created by ekansh on 23/1/15.
 */
class MyUserDetailsService implements UserDetailsService {

    static final GrantedAuthority NO_ROLE = new SimpleGrantedAuthority(SpringSecurityUtils.NO_ROLE)

    @Override
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User user = User.findByUsername(username)
        if(!user)
            throw new NoStackUsernameNotFoundException();
        
        Collection<GrantedAuthority> authorities;
        
        user.authorities.each {authority->
            authorities.collect(new SimpleGrantedAuthority(authority))
        }
        
        authorities = authorities ?: [NO_ROLE]

        // Return the Custom User object 
        return new MyUser(username, user.password, user.enabled, !user.accountExpired, !user.passwordExpired,!user.accountLocked, authorities, user.id, user.firstName+ user.lastName);
    }
}

So now we have a custom UserDetailsService that will load our MyUser  object in spring security authentication principal, instead of conventional GromUser object. You need to do one last thing to make things work. You need to override the UserDetailsService and tell spring security to use your custom UserDetailsService and you can do it like the following.
Add this in resources.groovy
userDetailsService(MyUserDetailsService)

Thats it, now you have can add any number of custom attributes of the User object to spring security authentication.

No comments:

Powered by Blogger.