Tobi
Tobi

Reputation: 2040

Grails Spring Security Rest Logout

I am using Grails 3.1.4 together with the Spring Security Rest Plugin 2.0.0.M2 for implementing a single page app with AngularJS. Login and validation is working perfectly fine, but when I call logout I get a 404 error.

When debugging, I get an exception in the plugin RestLogoutFilter:

try {
    log.debug "Trying to remove the token"
    tokenStorageService.removeToken accessToken.accessToken
} catch (TokenNotFoundException tnfe) {
    servletResponse.sendError HttpServletResponse.SC_NOT_FOUND, "Token not found"
}

Exception:

grails.plugin.springsecurity.rest.token.storage.TokenNotFoundException: 
Token eyJh... cannot be removed as this is a stateless implementation

Calling

tokenStorageService.loadUserByToken(accessToken.accessToken)

works, so the token certainly is in the tokenStorage.

My Spring Security configuration is

grails.plugin.springsecurity.userLookup.userDomainClassName = 'myapp.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'myapp.UserRole'
grails.plugin.springsecurity.authority.className = 'myapp.Role'
grails.plugin.springsecurity.userLookup.usernamePropertyName='email'
grails.plugin.springsecurity.rest.login.usernamePropertyName='email'
grails.plugin.springsecurity.rest.token.storage.gorm.usernamePropertyName='email'
grails.plugin.springsecurity.rest.logout.endpointUrl = '/api/logout'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
        [pattern: '/',               access: ['permitAll']],
        [pattern: '/error',          access: ['permitAll']],
        [pattern: '/index',          access: ['permitAll']],
        [pattern: '/index.gsp',      access: ['permitAll']],
        [pattern: '/shutdown',       access: ['permitAll']],
        [pattern: '/assets/**',      access: ['permitAll']],
        [pattern: '/**/js/**',       access: ['permitAll']],
        [pattern: '/**/css/**',      access: ['permitAll']],
        [pattern: '/**/images/**',   access: ['permitAll']],
        [pattern: '/**/favicon.ico', access: ['permitAll']],
        [pattern: '/api/logout',     access: ['isAuthenticated()']]
]

grails.plugin.springsecurity.filterChain.chainMap = [
        [pattern: '/assets/**',      filters: 'none'],
        [pattern: '/**/js/**',       filters: 'none'],
        [pattern: '/**/css/**',      filters: 'none'],
        [pattern: '/**/images/**',   filters: 'none'],
        [pattern: '/**/favicon.ico', filters: 'none'],
        [pattern: '/api/**',       filters: 'JOINED_FILTERS,-anonymousAuthenticationFilter,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter']
]

Is there an error in my config or any other thing wrong?

Upvotes: 2

Views: 1627

Answers (1)

Tobi
Tobi

Reputation: 2040

Found the answer minutes after asking the question.

The Spring Security Rest plugin documentation states:

Logout is not possible when using JWT tokens (the default strategy), as no state is kept in the server. If you still want to have logout, you can provide your own implementation by creating a subclass of JwtTokenStorageService and overriding the methods storeToken and removeToken. Then, register your implementation in resources.groovy as tokenStorageService.

However, a more rational approach would be just to remove the token from the client (eg, browser's local storage) and let the tokens expire (they will expire anyway, unlike with other storages like Memcached or Redis where they get refreshed on every access).

So just deleting the token on the client is sufficient if one is using JWT for authorization.

Upvotes: 3

Related Questions