Help Refreshing Yahoo's OAuth Access Token in Ruby - ruby

I'm at the point of involuntary hair loss while trying to refresh the Yahoo OAuth access token in Ruby.
Using the OmniAuth and OAuth gems, I'm able to get an access token from Yahoo, however it expires in one hour.
I'm following the Yahoo instructions to refresh an expired token, and am consistently returned a 401.
If someone could show me how to refresh the access token using the OAuth gem, I'd be greatly appreciative.

First, make sure you are saving your oauth_session_handle parameter from your original get_access_token call.
Then, when you are looking to refresh the access_token do something like this:
request_token = OAuth::RequestToken.new(consumer,
config["ACCESS_TOKEN"],
config["ACCESS_TOKEN_SECRET"])
token = OAuth::Token.new(config["ACCESS_TOKEN"],
config["ACCESS_TOKEN_SECRET"])
#access_token = request_token.get_access_token(
:oauth_session_handle => config["SESSION_HANDLE"],
:token => token)
... where ...
config["ACCESS_TOKEN"] is your old access token
config["ACCESS_TOKEN_SECRET"] is your old secret
config["SESSION_HANDLE"] is your oauth_session_handle
consumer is your OAuth::Consumer.new reference
I store the config variable in a yaml file and then load it on startup.
Remember to store the #access_token for next time.
I adapted this from an answer at YDN OAuth Forum.

Note: oauth_session_handle is returned as a param by the call to get_access_token:
access_token = request_token.get_access_token(:oauth_verifier => oauth_verifier)
oauth_session_handle = access_token.params['oauth_session_handle']
This was less than obvious from looking at the oauth-ruby/oauth code

Related

How JWT token lifetime in Spring boot actually works

I have implemented Oauth2.0 using JWT token until it seems to be basically worked with Spring Boot.
Question1 : I can call this URL in order to get 'access_token' and 'refresh_token' as a response.
https://myapp/oauth/token?grant_type=password&username=______&password=_______
But when every time I re-called the url, both access_token and refresh_token were regenerated and the old access_token can still be used until it expired.
Is it how it really works?
Regenerate both every time?
Question2 : Moreover, when I need to refresh my access_token, I called this URL
https://myapp/oauth/token?grant_type=password&username=______&password=_______
I, again, got both new access_token and new refresh_token. It is pretty strange for me that refresh_token was used to generate a newer refresh_token. But the old refresh_token can still works?!
If this already what JWT token should really work, please tell me why we need refresh_token when we can call the first URL to get new token anyway.
I have spent sometime on this but still could not find a clear reference mentioning these things.
If you could tell me the right flow that it should work I would appreciate that.
Thank you in advance.
Regarding Question 2: yes, you get a new access_token and refresh_token.
It's up to you (or whoever is responsible for the RefreshTokenProvider) that the resfresh_token can only be used once.
This blog article: http://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/ (scroll down to step 6) shows an example.

Instagram access_token returning BadRequest error

I'm working with the Instagram gem and getting an unexpected bad request error when calling Instagram.user_recent_media.
get '/api/photos' do
client = Instagram.client(:access_token => session[:access_token])
puts 'access token: ' << session[:access_token].inspect
id = params[:id]
photos = Instagram.user_recent_media(id, {:max_id => params[:max_id]})
end
It's throwing this error:
Instagram::BadRequest - GET https://api.instagram.com/v1/users/35099128/media/recent.json?client_id=12345&max_id=: 400: you cannot view this resource:
In the line where I put the access_token, it is printing out an access token so it clearly exists. When I curl the request I get the same error,
{"meta":{"error_type":"APINotAllowedError","code":400,"error_message":"you cannot view this resource"}}
but when I paste the request into the Instagram API console I get the expected results (JSON of user photo data). This is a user who I follow. For a little while I was having my access_token seemingly expire immediately and throwing a specific 'access token not valid' error but that has gone away, so I'm not sure what else could be causing this error.
The access_token or client_id that you are using in your Ruby code must be different from the one you are using in your web browser when you test the Instagram API console. That is the only explanation.
The ID that you are using in your question (35099128) is for a private Instagram account. The reason it works in the Instagram API console is because you are already following the private account with your Instagram account.
EDIT
To be 100% sure you have the correct access_token in your code you can try to make the query directly without the extraneous variables. Use the following format (taken from this question):
https://api.instagram.com/v1/users/20282699/media/recent?access_token=510573486.ab7d4b6.d8b155be5d1a47c78f72616b4d942e8d
Replace the user-id and access_token with the one your are printing in your code.
https://api.instagram.com/v1/users/35099128/media/recent?access_token=ACCESS_TOKEN_HERE
EDIT2
Since the access_token is definitely valid, it is clear that your request formed in the Ruby code is missing the access_token. The problem is this line:
photos = Instagram.user_recent_media(id, {:max_id => params[:max_id]})
has no knowledge of your access_token, likely because you're are not using the client object that you previously defined. Try changing it to this (or the proper equivalent):
photos = client.user_recent_media(id, {:max_id => params[:max_id]})

How to get a refresh token when using the Google Calendar API Ruby Library?

I'm a newbie trying to implement the Google Calendar API into a web-based app and after following the instructions that they provide to the t, fetching information only works for about 20 minutes (while the access token is still valid). I understand that you need a refresh token in order to generate a new access token, but running this script from the terminal (which google provided in their documentation) doesn't provide a refresh token.
The code I executed in terminal:
google-api oauth-2-login --scope=https://www.googleapis.com/auth/calendar --client- id=CLIENT_ID --client-secret=CLIENT_SECRET
This generated a .yaml file with all of my keys which looks like this:
---
mechanism: oauth_2
scope: SCOPE_HERE
client_id: CLIENT_ID_HERE
client_secret: CLIENT_SECRET_HERE
access_token: ACCESS_TOKEN_HERE
refresh_token:
And the code that they provided if the access token expires:
oauth_yaml = YAML.load_file('.google-api.yaml')
client = Google::APIClient.new
client.authorization.client_id = oauth_yaml["client_id"]
client.authorization.client_secret = oauth_yaml["client_secret"]
client.authorization.scope = oauth_yaml["scope"]
client.authorization.refresh_token = oauth_yaml["refresh_token"]
client.authorization.access_token = oauth_yaml["access_token"]
if client.authorization.refresh_token && client.authorization.expired?
client.authorization.fetch_access_token!
end
service = client.discovered_api('calendar', 'v3')
So, according the yaml file, client.authorization.refresh_token is always 'nil', and it never gets a new access token. Also, client.authorization.expired? always returns false, even after the app has stopped working.
I've seen some other questions on here pertaining to the same issue, but since I'm generating my tokens via a terminal command, I'm not really sure how to go about getting that refresh token.
You need to specify that you want offline access to get a refresh token: access_type=offline
See https://developers.google.com/accounts/docs/OAuth2WebServer#offline

Unable to refresh token after expiration

I can authenticate and fetch an access_token and the corresponding refresh_token fine (subsequent API interactions are also fine).
However, I seem to only be able to refresh a token (POST to /oauth/token with grant_type=refresh_token) before the access_token actually expires. After the expiration, the same refresh code (exactly that provided within the docs), returns with an error of invalid_grant.
I am using the soundcloud-ruby SDK, FWIW, but I can reproduce it through curl.
As an aside, I found some old messages from the Google Group mentioning that I can request a non-expiring token, but I do not see this mentioned anywhere in the docs. Is this still a viable option?
That is correct. Refresh tokens cannot be used after an access token expires.
You can request a non-expiring access token by specifying scope=non-expiring when constructing an authorization URL. To do this with the Ruby SDK, simply pass the additional params to the authorize_url method:
require 'soundcloud'
client = Soundcloud.new(
:client_id => 'YOUR_CLIENT_ID',
:client_secret => 'YOUR_CLIENT_SECRET',
:redirect_uri => 'REDIRECT_URI'
)
client.authorize_url(:scope => 'non-expiring')
The rest of the flow should be exactly the same (grab the 'code' parameter from the query string and make a POST request to /oauth2/token).

Ruby twitter client

I'm trying to create a ruby-based twitter client where I can post my status from command-line using ruby. I'm trying to understand the oauth right now, and it confused me a little bit. If I'm building a web application, I can provide a callback url when the request token is complete. How would I do that from the command-line? I don't want ruby to print out the authorized and copy and paste the url and click 'Allow' to get the token. I found something about out-of-band exchange or PIN. How would I do that with OAuth library in ruby, please thank you very much.
To use the callback url mechanism, you application should be a web application. It seems you are developing desktop application and if that's the case, you should follow "PIN code" flow by supplying an oauth_callback_url of "oob" (out-of-band) when you request token. Like this,
https://api.twitter.com/oauth/request_token?oauth_callback=oob
If you properly set a header of this HTTP request (setting HTTP header is the key part of OAuth and I think you already know how to do this), Twitter will give oauth_token, oauth_token_secret and oauth_verifier. Let's call this token "request_token". You need it to get "access_token" later.
Once you have request_token, you need to open web page with the below url
http://api.twitter.com/oauth/authorize?oauth_token=request_token
This will open the authorization page and let a user to decide whether the user wants to allow your application to access his or her Twitter account. If the use says okay, then Twitter gives PIN code. You need to allow a user to type the PIN code so that you can save it.
Now, it's time to get another token ("access_token") by using your comsumer_key / secret, request_token and the PIN code. You should set header with all these values correctly and do HTTP request again with this url,
https://api.twitter.com/oauth/access_token
If Twitter accepts your "access_token" request, it will give you oauth_token, oauth_token_secret, user_id and screen_name. Let's call this token "access_token". Now, you can perform any OAuth required Twitter API by using access_token and its secret (oauth_token_secret). You can save the two values in a file and keep using them whenever you need to access the user's Twitter account. The values will be always valid until the user revokes the access to your application.
I don't know Ruby but if you know how to perform HTTP/HTTPS requests (GET / POST) with custom headers in Ruby, this PIN code flow should work fine if you follow Twitter API document carefully. Good Luck!
It will ask for the PIN code until you specify the oauth_callback when getting the request token, not when forwarding the user to the authorization url
#consumer = OAuth::Consumer.new(
TWITTER_CONSUMER_KEY,
TWITTER_CONSUMER_SECRET,
{:site=>"https://api.twitter.com"})
#request_token = #consumer.get_request_token( :oauth_callback => CALLBACK_URL )
This was the result of surfing several hours of incomplete documentation.
use Twitter gem, it will make things easier for you. http://rdoc.info/gems/tweeter/2.0.0/frames

Resources