I'm having some trouble making a "refresh_token" request with Spring Security Rest in a Grails 3 application. I have an application with both a web front-end and some Rest endpoints, and everything else seems to be working fine. The web app behaves as expected and, when I make a login request via curl with
curl -i -X POST localhost:8080/api/login \
-H "Content-Type: application/json" \
-d '{"username":"johndoe", "password":"johndoepassword"}'
I get back the expected response (I have truncated the tokens):
{
"username":"johndoe",
"roles":["ROLE_USER"],
"token_type":"Bearer",
"access_token":"eyJhbGciOiJIUzI1NiJ9.xxxxxx",
"expires_in":3600,
"refresh_token":"eyJhbGciOiJIUzI1NiJ9.xxxx"
}
In the actual application, I can add the access_token to the header and authenticate with no problem for the duration of the session. However, I get a 403 when I hit the "refresh token" endpoint with
curl -i -X POST localhost:8080/oauth/access_token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token&refresh_token=eyJhbGciOiJIUzI1NiJ9.xxxx"
This all seems pretty straightforward in the docs, but I'm obviously doing something wrong. Here's what I think is the relevant portion of my config file:
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
[pattern: '/error', access: ['permitAll']],
[pattern: '/login', access: ['permitAll']],
[pattern: '/login/**', access: ['permitAll']],
[pattern: '/oauth/**', access: ['permitAll']],
[pattern: '/user/register', access: ['permitAll']],
[pattern: '/user/register/**', access: ['permitAll']],
[pattern: '/user/submitRegistration', access: ['permitAll']],
[pattern: '/logoff', 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: '/surveyAdmin/**', access: ['ROLE_ADMIN']] ,
[pattern: '/**', access: ['ROLE_USER']]
]
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'
],
[
pattern: '/rest/**',
filters: 'restTokenValidationFilter,restExceptionTranslationFilter,filterInvocationInterceptor'
],
[pattern: '/**', filters: 'JOINED_FILTERS']
]
Can anyone suggest a way through here?
Thanks, Alex
As so often happens, I found the answer shortly after posting the question. I'm using a custom user class that implements org.springframework.security.core.userdetails.UserDetails but does not extend org.springframework.security.core.userdetails.User. The plugin assumes the principal can be cast to a "User" object, which was causing the user lookup/token generation to fail. Either changing my custom class to extend User or overriding the refreshToken method in the plugin to accept my custom user class got things working.