Spring Social
  1. Spring Social
  2. SOCIAL-263

Refresh token not supported for OAuth2

    Details

    • Type: New Feature New Feature
    • Status: Open
    • Priority: Blocker Blocker
    • Resolution: Unresolved
    • Affects Version/s: 1.0.0.RELEASE
    • Fix Version/s: 2.0.0 Backlog
    • Component/s: API Binding
    • Labels:
      None

      Description

      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.

        Activity

        Hide
        Craig Walls added a comment -

        Moved to 1.1.0.M4, as it requires more research. In the meantime, ReconnectController can handle this kind of scenario generically (albeit while ignoring and not using any refresh token).

        Show
        Craig Walls added a comment - Moved to 1.1.0.M4, as it requires more research. In the meantime, ReconnectController can handle this kind of scenario generically (albeit while ignoring and not using any refresh token).
        Hide
        Craig Walls added a comment - - edited

        Note, I'll also need to find an OAuth 2 provider that uses refresh tokens to try this out with. Both Facebook and LinkedIn force a redirect-based renewal of tokens instead of using refresh tokens. Google+ is a likely candidate for this.

        Show
        Craig Walls added a comment - - edited Note, I'll also need to find an OAuth 2 provider that uses refresh tokens to try this out with. Both Facebook and LinkedIn force a redirect-based renewal of tokens instead of using refresh tokens. Google+ is a likely candidate for this.
        Hide
        Craig Walls added a comment -

        One option that I'm considering here (and that makes a lot of sense) is to handle this in the API binding's error handler, or better in a common base class for all API binding error handlers.

        This would have some minimal impact to API binding implementations, but very minimal. And handling authorization exceptions in an error handler makes sense. An added plus is that some common non-authorization errors could be handled in the base class, too...alleviating the burden on the API binding implementation to handle those themselves.

        Show
        Craig Walls added a comment - One option that I'm considering here (and that makes a lot of sense) is to handle this in the API binding's error handler, or better in a common base class for all API binding error handlers. This would have some minimal impact to API binding implementations, but very minimal. And handling authorization exceptions in an error handler makes sense. An added plus is that some common non-authorization errors could be handled in the base class, too...alleviating the burden on the API binding implementation to handle those themselves.
        Hide
        marc schipperheyn added a comment -

        If this is a feature that is hard to implement in a cross vendor way, why not create some logical hooks for the various implementations to develop against and provide a simple fallback that supports removing the connection and recreating it

        Show
        marc schipperheyn added a comment - If this is a feature that is hard to implement in a cross vendor way, why not create some logical hooks for the various implementations to develop against and provide a simple fallback that supports removing the connection and recreating it
        Hide
        Craig Walls added a comment -

        Changing issue to New Feature, as opposed to a bug. Also moving to 2.0.0 Backlog. At the moment the main Spring Social provider modules that rely on OAuth 2 are Facebook and LinkedIn, neither of which support refresh tokens. In those cases, a reauthorization flow (as provided by ReconnectFilter) is the only way to renew a connection.

        This issue will be reconsidered in Spring Social 2.0.0 for providers who support refresh tokens.

        Show
        Craig Walls added a comment - Changing issue to New Feature, as opposed to a bug. Also moving to 2.0.0 Backlog. At the moment the main Spring Social provider modules that rely on OAuth 2 are Facebook and LinkedIn, neither of which support refresh tokens. In those cases, a reauthorization flow (as provided by ReconnectFilter) is the only way to renew a connection. This issue will be reconsidered in Spring Social 2.0.0 for providers who support refresh tokens.

          People

          • Assignee:
            Craig Walls
            Reporter:
            Bozhidar Bozhanov
          • Votes:
            12 Vote for this issue
            Watchers:
            12 Start watching this issue

            Dates

            • Created:
              Updated: