Reputation: 2040
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
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