Announcement Announcement Module
Collapse
No announcement yet.
Automatic use refresh token Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Automatic use refresh token

    Short version: does OAuth2RestTemplate support automatical refresh of a expired token, given that a refresh token is provided?

    The scenario: I have configured a OAuth2RestTemplate with all the stuff needed to get the right result with a
    restTemplate.getForObject(remoteResourceUrl, ObjectNode.class);

    and I have also set the refresh token to the access token. But if the access token is expired, I get a 401. In my custom oauth2 implementation for the specific service (salesforce) the difference in the POST for the refresh token is that, other than the refresh token itself, the grant type is "refresh_token" rather than "authorization_code"

    Now, what I was going to implement in my custom code is a mechanism that can handle the expired access token (401 answer) and automatically send a refresh request and store the new token.

    I expected the spring implementation to do the same and I bet it can, I just do not know how.

  • #2
    I'm afraid we don't have the code in there for that, yet. It was intended to be added.

    We'd love it if you could share your own code (or even propose a patch) and attach it to a JIRA issue.

    Thanks!

    Comment


    • #3
      Originally posted by stoicflame View Post
      I'm afraid we don't have the code in there for that, yet. It was intended to be added.

      We'd love it if you could share your own code (or even propose a patch) and attach it to a JIRA issue.

      Thanks!
      I think I can implement a first version quickly on my custom code and report it to the spring-oauth project this afternoon.
      I'll let you know the JIRA issue number here.

      Comment


      • #4
        I've explored the spring code and found that DefaultOAuth2SerializationService.deserializeError already handles expired tokens, throwing a pretty clear ExpiredTokenException.

        Problem is, the server should return a specific message in the header of the 401 response and Salesforce REST API, which I am using now, does not.
        Spring OAuth2ErrorHandler look in the headers and here's what Salesforce answering to me:

        response.getHeaders()
        (org.springframework.http.HttpHeaders) {Server=[], WWW-Authenticate=[Token], Content-Type=[application/json; charset=UTF-8], Content-Length=[75], Date=[Fri, 10 Dec 2010 07:12:47 GMT]}

        WWW-Authenticate=[Token] is what Oauth2ErrorHandler is searching and does not contain enough information.

        I do not know if the Spring implementation is based on some OAuth2 standard or not. If so, someone should call Salesforce guys and tell em to fix this If not well... we should find another road.
        I haven't find anything on SF REST API doc [1]

        Anyway, problem is that oauth2 access token expiration is not set by specification: Facebook token does not expired for example [2]
        So I do not think oauth providers will expose an API to query for token expire time.

        So I think that I'll do a custom implementation that retry at least one time if it receives a 401 and it has been provided a refresh token. I'll see how to adapt that to Spring implementation.

        [1] http://developer.force.com/REST
        [2] http://developers.facebook.com/docs/authentication

        Comment


        • #5
          FYI, the current implementation is based on oauth v2 draft 10:

          http://tools.ietf.org/html/draft-ietf-oauth-v2-10

          Comment


          • #6
            I think the refresh token issue can be resolved this way, though the code for obtaining a new token still need to be written (AFAIK it is not yet implemented):

            Code:
            public class OAuth2RestTemplate extends RestTemplate {
              ...
            
              @Override
              protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor) throws RestClientException {
                try {
                  return super.doExecute(url, method, requestCallback, responseExtractor);
                } catch (ExpiredTokenException e) {
                  OAuth2AccessToken accessToken = OAuth2SecurityContextHolder.getContext().getAccessTokens().get(resource.getId());
                  if (accessToken.getRefreshToken() != null) {
                    // TODO: get a new token, store it in the context
                    // now retry
                    return super.doExecute(url, method, requestCallback, responseExtractor);
                  }
                }
              }
            }

            Comment


            • #7
              Yes I have implemented a similar solution in my custom code.
              My specific problem is that Salesforce REST Oauth API does not correctly implement oauth2 reference so ExpiredTokenException is never raised.
              In fact I actually catch a generic 401 exception and try the refresh one time to make it work.

              Comment

              Working...
              X