Search code examples
grailsspring-securitygrails3

Grails 3.2.8 not able to get springSecurityService.currentUser in controller


I'm unable to get springSecurityService.currentUser from a controller in Grails 3.2.8.

Please note that Grails 3.2.8 made some performance improvements not in previous versions that seem to be breaking Spring Security Core. As per Grails 3.2.8 dependency injection in domain classes, I set grails.gorm.autowire = true, which fixed that incompatibility.

Steps to reproduce:

  1. Create a new Grails 3.2.8 web app with Spring Security 3.1.1 using Roles and Groups.

  2. In application.yml, set grails.gorm.autowire = true

  3. In Bootstrap:

    def init = { servletContext ->
        User user = new User(username: 'foo', password:'foo').save(flush: true)
        Role role = new Role(authority: 'SomeRole').save(flush: true)
        RoleGroup roleGroup = new RoleGroup(name: 'SomeRole').save(flush: true)
        RoleGroupRole.create(roleGroup, role)
        UserRoleGroup.create(user, roleGroup)
    }
    
  4. Create a controller TestController:

    @Secured(['SomeRole'])
    class TestController {
        def springSecurityService
    
        def index() {
            println "springSecurityService==null? ${(springSecurityService==null).toString()}"
            println "SecurityContextHolder.context==null? ${(SecurityContextHolder.context==null).toString()}"
            println "SecurityContextHolder.context?.authentication==null? ${(SecurityContextHolder.context?.authentication==null).toString()}"
            println "springSecurityService.principal==null? ${(springSecurityService.principal==null).toString()}"
            println "springSecurityService.currentUser==null? ${(springSecurityService.currentUser==null).toString()}"
    
            render "1" //Render something so we don't get an exception.
        }
    }
    
  5. Start up the server and go to /test. The output is:

    springSecurityService==null? false
    SecurityContextHolder.context==null? false
    SecurityContextHolder.context?.authentication==null? true
    springSecurityService.principal==null? true
    springSecurityService.currentUser==null? true`
    

Is there a good workaround?


Solution

  • If SecurityContextHolder.context is not null (it should never be null) but SecurityContextHolder.context?.authentication is null, then this is probably not a Grails or a plugin issue - you're not authenticated. So there's no principal to get the cached user id from (i.e. springSecurityService.principal is null as your output shows) and there's no way to retrieve the current User instance.