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:
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:
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?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!!
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With