Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Google Client API - unable to exchange a refresh token for access token

After struggling with some SSL issues on my machine, I'm still trying to access a user's Blogger account through the Google Ruby Client API. I'm using the following:

  • Rails 3.2.3
  • Ruby 1.9.3
  • oauth2 (0.8.0)
  • omniauth (1.1.1)
  • omniauth-google-oauth2 (0.1.13)
  • google-api-client (0.4.6)

I can successfully authenticate users and access their blogs through the Google API at the time of authentication. When a user logs in, I store the access_token and refresh_token I receive from Google. and everything works great until the access_token expires. I'm trying to build the functionality that exchanges the refresh_token for a new access_token, but keep coming up against walls. Using the client documentation as an example, this is the code I'm using:

  client = Google::APIClient.new
  token_pair = auth.oauth_token   # access_token and refresh_token received during authentication

  # Load the access token if it's available
  if token_pair  
    client.authorization.update_token!(token_pair.to_hash)
  end            

  # Update access token if expired
  if client.authorization.refresh_token && client.authorization.expired?
    client.authorization.fetch_access_token!
  end

  blogger = client.discovered_api('blogger', 'v3')
  result = client.execute(
      api_method: blogger.blogs.list_by_user,
      parameters: {'userId' => "self", 'fields' => 'items(description,id,name,url)'},
      headers: {'Content-Type' => 'application/json'})

This code works perfectly while the access_token is valid. As soon as it expires though, I'm seeing 2 problems:

  1. Even though I know the token is expired (I've checked expires_at value in the database), client.authorization.expired? returns false -- is there a different way I can check the expiration of the token besides using the value in the database?
  2. When I force the execution of client.authorization.fetch_access_token! I get an invalid_request error.

Can someone please let me know how I can exchange a refresh_token for a new access_token using the client API? Even if you know how to do it in another language, that would be a big help as I can then try to Rubyfy it. Thanks!!

like image 792
cerrina Avatar asked Sep 24 '12 20:09

cerrina


People also ask

Can not get refresh token?

Go to the page showing Apps with access to your account: https://myaccount.google.com/u/0/permissions. Under the Third-party apps menu, choose your app. The next OAuth2 request you make will return a refresh_token (providing that it also includes the 'access_type=offline' query parameter.

How do I refresh my access token?

To refresh your access token as well as an ID token, you send a token request with a grant_type of refresh_token . Be sure to include the openid scope when you want to refresh the ID token. If the refresh token is valid, then you get back a new access and the refresh token.

How do I get refresh token for Google API postman?

Now go to Variables tab in this collection and paste your client Id and secret. Also enter appropriate scope. In Authorization tab of collection, just hit "Get New Access Token". That will open up a web browser window asking for your authentication.


1 Answers

You may have already found this, but you can read through the whole process here at google: https://developers.google.com/accounts/docs/OAuth2WebServer

The omniauth-google-oauth2 strategy already takes care of setting the access_type and approval_prompt so getting a refresh token is just a matter of posting to https://accounts.google.com/o/oauth2/token with grant_type=request_token

Here is roughly the code I use:

def refresh_token
  data = {
    :client_id => GOOGLE_KEY,
    :client_secret => GOOGLE_SECRET,
    :refresh_token => REFRESH_TOKEN,
    :grant_type => "refresh_token"
  }
  @response = ActiveSupport::JSON.decode(RestClient.post "https://accounts.google.com/o/oauth2/token", data)
  if @response["access_token"].present?
    # Save your token
  else
    # No Token
  end
rescue RestClient::BadRequest => e
  # Bad request
rescue
  # Something else bad happened
end
like image 169
brimil01 Avatar answered Oct 18 '22 22:10

brimil01