google oauth and refresh token confusion/questions

335 Views Asked by At

I had expected the refresh of an expired access token to happen during the authentication process instead of during an api access.

I think I understand why this happens - authorization is done once but an access token can expire at any time, therefore a refresh attempt needs to be attempted whenever the token is determined to be expired.

I'd like to confirm this is the right interpretation of what's going on.

My first clue was the part of the docs that said

If you use a Google API Client Library, the client object refreshes the access token as needed as long as you configure that object for offline access.

I am using the following:

google-oauth-client 1.24.1
google-oauth-client-java6 1.24.1
google-oauth-client-jetty 1.24.1

When I run with a completely invalid access token ("i am no good") and a valid refresh token and execute a DCM API call to a com.google.api.client.googleapis.services.json.AbstractGoogleJsonClient subclass, I observe the following behavior:

control passes to com.google.api.client.auth.oauth2.Credential at method:

public final boolean refreshToken() throws IOException {
  lock.lock();
    try {
      try {
        TokenResponse tokenResponse = executeRefreshToken();
        if (tokenResponse != null) {
          setFromTokenResponse(tokenResponse);
          for (CredentialRefreshListener refreshListener : refreshListeners) 
          {
            refreshListener.onTokenResponse(this, tokenResponse);
          }
          return true;
        }
      } catch (TokenResponseException e) {
        boolean statusCode4xx = 400 <= e.getStatusCode() && e.getStatusCode() < 500;
        // check if it is a normal error response
        if (e.getDetails() != null && statusCode4xx) {
          // We were unable to get a new access token (e.g. it may have been revoked), we must now
          // indicate that our current token is invalid.
          setAccessToken(null);
          setExpiresInSeconds(null);
        }
        for (CredentialRefreshListener refreshListener : refreshListeners) {
          refreshListener.onTokenErrorResponse(this, e.getDetails());
        }
        if (statusCode4xx) {
          throw e;
        }
      }
    return false;
  } finally {
    lock.unlock();
  }
}

This goes out and gets a new access token as long as the refresh token is valid (i've tried using an invalid refresh token and watched it fail).

Upon successful retrieval of a new access token, control passes to

refreshListener.onTokenErrorResponse(this, e.getDetails());

The token is inserted into the proper objects and access continues.

If I run with a bad refresh token the above method fails with:

com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request { "error" : "invalid_grant", "error_description" : "Bad Request" }

Can anyone confirm I've got the right general idea?

0

There are 0 best solutions below