Search code examples
grailsgroovyspring-securitygrails-orm

2 UserDomainClass in Spring Security


In the existing Grails application, I have 2 user domains, say UserAdmin and UserBasic. Both these domains have few common fields and also some distinct fields(respective to domain) and currently the login/logout is maintained using sessions for both types of users separately. I want to integrate spring-security in the existing application.

What would be the best approach to do it ? Considering that both domains also have different field. Can we inherit both the domains in a single domain and use it as Spring Security user class ? Please suggest.


Solution

  • Spring Security Core uses one of the implementations of UserDetails interface as a projection of authenticated user. Grails provides e.g. GrailsUser class:

    https://github.com/grails-plugins/grails-spring-security-core/blob/master/src/java/grails/plugin/springsecurity/userdetails/GrailsUser.java

    Keep in mind, that this class is not a "domain" class in terms of Grails application layout - it does not get persisted in the database, it's just a projection of the user that is bounded to the current session.

    If you have 2 different domain classes that represents users in your application, you can try to provide your own implementation of UserDetailsService, e.g.

    class CustomUserDetailsService implements UserDetailsService {
    
        @Override
        UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    
            // 1. Check if expected user is type of UserBasic
            // 2. If not, check if expected user is type of UserAdmin
            // 3. If nothing found, throw an exception
            // 4. Otherwise create new GrailsUser instance using UserBasic or UserAdmin data
            // 5. Return created GrailsUser instance
    
            return null
        }
    }
    

    Then you have to inject your implementation by adding or modifying an entry in grails-app/conf/spring/resources.groovy e.g.

    // Place your Spring DSL code here
    beans = {
        // other beans goes here
        // ...
    
        userDetailsService(CustomUserDetailsService)
    }
    

    This is just a concept that you can start from.