Search code examples
grailsspring-securitypre-authentication

Grails pre-authenticated scenario


I'm trying to configure a Grails app in a pre-authenticated scenario, using Spring Security Core.

So I wrote a custom authentication filter:

class MyAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {
    protected getPreAuthenticatedPrincipal(request) { "my_username" }
    protected getPreAuthenticatedCredentials(request) { "N/A" }
}

added it to Spring:

beans = {
    myAuthenticationFilter(MyAuthenticationFilter) {
        authenticationManager = ref('authenticationManager')
        checkForPrincipalChanges = true
    }
}

and registered it in BootStrap, with position PRE_AUTH_FILTER:

class BootStrap {
    def init = { servletContext ->
        SpringSecurityUtils.clientRegisterFilter('myAuthenticationFilter',
            SecurityFilterPosition.PRE_AUTH_FILTER.order)
    }
}

Config.groovy only has the standard User, Role, and UserRole class names, plus some staticRules.

Inside the filter, I tried returning all sorts of things from its getPreAuthenticatedPrincipal() method: the user id, the user id as a string, its username, the User object itself… I can see that my filter is being called for each request (which is what I want, having set checkForPrincipalChanges = true) no matter what I return from it, the current user remains anonymous: springSecurityService.principal is still __grails.anonymous.user__

What do I need to change in my setup, to be able to authenticate my users, with their existing groups and roles? I don't want to write an additional authentication provider, I'm fine with Grails's standard daoAuthenticationProvider. Do I need to return something specific from my filter? Do I need to setup some other Spring classes?


Solution

  • I solved it. I'm documenting it here in case somebody else needs to do the same.

    Basically the missing piece was to configure a new PreAuthenticatedAuthenticationProvider as the only provider. No additional code needed, just define it in resources:

    myAuthenticationProvider(PreAuthenticatedAuthenticationProvider) {
        preAuthenticatedUserDetailsService = ref('authenticationUserDetailsService')
    }
    

    and set it as the only provider in Config:

    grails.plugin.pringsecurity.providerNames = ['myAuthenticationProvider']
    

    Then, from the authentication filter, just return the username of the pre-authenticated user, or null if none (the anonymous user.)