8

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.

Eric
  • 5,815
  • 3
  • 25
  • 34

2 Answers2

11

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
Blake
  • 1,168
  • 1
  • 14
  • 15
  • where would you implement this in your rails app? for example I have a get request to retrieve the users contacts using httparty which sends the token, how would i say post the refresh token if the token has expired? – Richlewis Mar 30 '13 at 13:34
  • The code I posted above is the code that does the POST request to refresh the token. After you perform your GET request, I would check to see if the response code is equal to 401, that is typically the code you'll get when you need to refresh your token. If the HTTParty response code == 401 then run my code (adjusted for your needs). – Blake Apr 01 '13 at 23:18
5

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.

mimming
  • 13,974
  • 3
  • 45
  • 74