Type: New Feature
Affects Version/s: 1.0.0.RELEASE
Component/s: API Binding
OAuth2 has two tokens - an access token, used for every request, and a refresh token, used to obtain a new access token once the original expires.
Google+ is an OAuth2 provider that, unlike Facebook, supports and requires a refresh token. However, I don't see such a facility in spring-social. There is OAuth2Template.refreshAccess(..), but it can't be invoked properly. In theory, a refresh token should be used when the server responds with 401 to an access token (meaning the token has expired or is otherwise invalid). However, neither AbstractOAuth2ApiBinding, nor AbstractOAuth2ServiceProvider, nor RestTemplate offer any facility to do that.
- AbstractOAuth2ServiceProvider's getApi(..) methods requires only an access token (what happens if it is invalid? Where should the refresh token come from?)
- AbstractOAuth2ApiBinding again has only an access token, and even if there was a facility to accommodate the refresh-on-failure, the refresh token isn't stored anywhere
- RestTemplate offers a ResponseErrorHandler and a list of request interceptors. Neither of them can be used to make a new request in order to refresh the access token (let alone return that token to the caller, to be persisted). a ResponseErrorHandler can send a refreshAccess request, and can persist the result, but cannot change the result from the restTemplate invocation. a request interceptor can do nothing about the response (logically)
Currently I have worked this around by using the refresh token on every request (passing it instead of accesstoken to getApi()), and using the thus-obtained access token to make authenticated calls. This relies on the fact that google+ in particular does not change the refresh token, so it remains a valid way to make requests forever. However, by spec, the provider can choose to renew the refresh token as well. Even in that case the workaround can be used (just persist the new refresh token), but either way it goes against the idea of OAuth. The refresh token should be used only if the original token has expired. I don't know if google won't at some point "frown upon" frequent refreshes and impose some limit.
(I choose an issue type of "bug", because it is bug per the OAuth2 (latest draft) spec, but feel free to change it to "improvement". I prioritize it as "blocker", because I am publishing a google+ API based on spring-social, and it is not a good idea to spread software that relies on workarounds)
My suggestion would be to let the error handler change the result of the resttemplate invocation, and also provide an error handler that checks for 401 and tries to refresh the token. That handler should have some callback that informs the application about the change, so that the new token(s) can be persisted.