Andrey Yaskulsky
Andrey Yaskulsky

Reputation: 2516

force logout for authenticated user using spring security plugin

I have the following problem: I have default User and Role domains and I use spring security plugin. There is a special requirement which says that if admin deletes User with USER_ROLE and this user is authenticated at the moment then this user should be kicked out of application immediately. Is it possible to programmatically make logout for the user if we have this user's object instance? Somethig like

def(User user) {

    someSpringService.forceLogout(user)

}

Thank you!

Upvotes: 0

Views: 1781

Answers (1)

Shabnam
Shabnam

Reputation: 91

I am a newbie to grails. Recently I had the task of force logging out a user on change of his privileges by admin. So,After some research here is my solution. I am keeping track of the users sessions and once his session is changed I simply expire his active sessions.

In web.xml file, add this listener

<listener>
<listener-class>    
    org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>

In resources.groovy

import org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy
import org.springframework.security.web.session.ConcurrentSessionFilter
import org.springframework.security.core.session.SessionRegistryImpl
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy

beans = {
// bind session registry
    sessionRegistry(SessionRegistryImpl)
    sessionAuthenticationStrategy(ConcurrentSessionControlStrategy,sessionRegistry){ 
        maximumSessions = -1 }
    concurrentSessionFilter(ConcurrentSessionFilter){
    sessionRegistry = sessionRegistry
    expiredUrl = '/login/auth?f=true'
    }
}

In controller

def expireSession(User user) {
    log.info("Process to expire session begins")
    def orginalUser = springSecurityService?.principal.username
    log.info("session infos for all principals: ${sessionRegistry.getAllPrincipals()}")
    sessionRegistry.getAllPrincipals()?.each { princ ->
        def allSessions = sessionRegistry.getAllSessions(princ, true);
        log.info("all sessions: ${allSessions}")
        log.info("principal: $princ; email: ${user?.email}; username: ${princ?.username}")
        if(princ?.username?.equals(user?.email)) {      //killing sessions only for user ([email protected])
            sessionRegistry.getAllSessions(princ, true)?.each { sess ->
                log.info("session: ${sess}; expiring it")
                if(sess.expireNow())
                    log.info("----session expired----")
                springSecurityService?.reauthenticate(user?.email)
                springSecurityService?.reauthenticate(orginalUser)
            }

        }
    }
}

In RequestFilters.groovy, where on each request we test if the session is valid or expired

class RequestFilters {

def springSecurityService
def sessionRegistry

def filters = {
    all(controller:'*', action:'*') {
        before = {
            log.info(controllerName + '/' + actionName +  " : " + params)
            log.info("request ${request}; session: ${request?.session}")
            def sessInfo = sessionRegistry.getSessionInformation(request?.session?.id)
            log.info("sessionRegistry: ${sessionRegistry}")
            log.info("Session Id: ${request?.session?.id}")
            log.info("session info: ${sessInfo}; is expired: ${sessInfo?.expired}")
            if(sessInfo?.expired==true)
                response.sendRedirect(grailsApplication.config.grails.serverURL+"/j_spring_security_logout");

        }
        after = { Map model ->

        }
        afterView = { Exception e ->

        }
    }     
}

Upvotes: 1

Related Questions