Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I refresh my google_oauth2 access token using my refresh token?

I have a RoR app where I am authenticating against Google using omniauth and google_oauth2 where I am requesting offline access.

How do I use my refresh token to request a current access token? Also, how can I refresh my access token when it no longer works? I don't want to have any user interface in this situation, assuming of course that the authorization hasn't been taken away.

like image 906
Eric Avatar asked Oct 09 '12 03:10

Eric


2 Answers

For an example using the Ruby HTTParty gem:

Where @auth is an ActiveRecord record that stores the auth keys for the specific user you are trying to refresh tokens for.

  # Refresh auth token from google_oauth2 and then requeue the job.
  options = {
    body: {
      client_id: <YOUR GOOGLE API CLIENT ID HERE>,
      client_secret: <YOUR GOOGLE API SECRET KEY HERE>,
      refresh_token: @auth.refresh_token,
      grant_type: 'refresh_token'
    },
    headers: {
      'Content-Type' => 'application/x-www-form-urlencoded'
    }
  }
  @response = HTTParty.post('https://accounts.google.com/o/oauth2/token', options)
  if @response.code == 200
    @auth.token = @response.parsed_response['access_token']
    @auth.expires_in = DateTime.now + @response.parsed_response['expires_in'].seconds
    @auth.save        
  else
    Rails.logger.error("Unable to refresh google_oauth2 authentication token.")
    Rails.logger.error("Refresh token response body: #{@response.body}")
  end
like image 62
Blake Avatar answered Oct 11 '22 10:10

Blake


I don't see anything in google_oauth2 that handles fetching a new access_token with a refresh token, so it looks like you'll need to make the exchange directly.

Google's official OAuth 2.0 documentation explains how to do this at a low level. Within your server-side code, use your favorite HTTP client to construct a request that looks like this:

POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded

client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
refresh_token=REFRESH_TOKEN&
grant_type=refresh_token

where CLIENT_ID and CLIENT_SECRET are the same ones you used for the original authentication and REFRESH_TOKEN is the refresh token from the original authentication flow. If the exchange is successful, you'll receive a fresh access token in a response that looks something like this:

{
  "access_token":"1/fFBGRNJru1FQd44AzqT3Zg",
  "expires_in":3920,
  "token_type":"Bearer",
}

You can follow this process to grab a new access token whenever you need one. You can either use the expires_in value to estimate when you will need a new one, or attempt a refresh whenever your API request responds with a 401 HTTP status.

like image 28
mimming Avatar answered Oct 11 '22 10:10

mimming