Client get_token method raises error incorrectly #75

Open
amnwebmaster opened this Issue Sep 28, 2011 · 13 comments

Projects

None yet
@amnwebmaster

Calling @client.auth_code.get_token(...) to Facebook gives an OAuth2::Error

Facebook correctly returns the access token but not as a hash but a string hence client.rb line 130 is incorrect

raise Error.new(response) unless response.parsed.is_a?(Hash) && response.parsed['access_token']

Should be:
raise Error.new(response) unless response.parsed['access_token']

@dexterdeng

I got the same issue

@acvwilson

Also, having this issue.

@acvwilson

You can add a parser with the code below. If you're using rails, a good spot to put it might be config/initializers/oauth2.rb. This assumes the body of the response will look something like this: "access_token=54626|345_435-534523DSF".

OAuth2::Response.register_parser(:text, 'text/plain') do |body|
  key, value = body.split('=')
  {key => value}
end

This will overwrite the existing :text parser. If that causes problems, you could change the parser to :facebook instead of :text and pass :parse => :facebook into the params of the get_token function when you call it, though I haven't tried that.

@yosiyuki

Thanks, acvwilson. Your solution helped me.

@kyleschmolze

Thanks, acvwilson.

I ran into a problem because facebook actually returns a string with 2 keys, the token and the seconds until expiration.
So the string facebook returns looks more like:

access_token=abcdef_some_fb_code&expires=5000

Current Fb Docs here: http://developers.facebook.com/docs/authentication

So my token was being set to 'abcdef_some_fb_code&expires' with your fix. This minor tweak:

OAuth2::Response.register_parser(:text, 'text/plain') do |body|
  token_key, token_value, expiration_key, expiration_value = body.split(/[=&]/)
  {token_key => token_value, expiration_key => expiration_value}
end

Fixed it for me.

@skogsmaskin

I had the same kind of trouble, only my problem was:

  1. I didn't use HTTPS to talk to the OAuth 2 API on the provider server (resulting in an OAuth2::Error in lib/omniauth/strategies/oauth2.rb:66)
  2. The user hash on the server didn't respond with Content-type: application/json in the header (resulting in an oAuth2::Error in my strategy regarding access_token.get(userinfo_url) )

It was not the easiest stuff to debug, as the OAuth2:Error did not contain any extended info, and I had to raise them inside my strategy, overriding the OmniAuth::Strategies::OAuth2 methods.

On my wish list for the next release, is an easier way to debug these kind of problems when developing a custom strategy on the application side (the application which is using the strategy). Omniauth is "eating" the exception details, just showing a "invalid_credentials" error in that scope.

@najamkhn

Same issue.. Fails to work with Github OAuth API..

require 'oauth2'

client = OAuth2::Client.new('< key >', '< secret >', :site => 'https://github.com/login/oauth/authorize')
auth_url = client.auth_code.authorize_url(:redirect_uri => 'https://github.com/login/oauth/access_token')
token = client.auth_code.get_token('authorization_code_value', :redirect_uri => 'https://github.com/login/oauth/access_token')
@az-azza
az-azza commented Feb 24, 2012

The same goes for Yammer API. I noticed that in AccessToken initialization method access_token parameter is removed from hash and its content is cast to String and stored under token attribute...with yammer api it does contain a number of additional parameters and values like so:

"access_token": {
"view_subscriptions": true,
"expires_at": null,
....
"token": "xxxxxxxx",
}

so by casting to s it becomes just a blob of chars.

My quick workaround was a custom parser(based on previous comment) that adds custom parameter:

OAuth2::Response.register_parser(:ytext, 'text/plain') do |body|
parsed_body = JSON.parse(body)
parsed_body['raw_access_token'] = parsed_body['access_token']['token']
parsed_body
end

@isbaysoft

I've had same issue, just set parser type to solve this issue in your provider options if you have response body as json.

option :token_params, {:parse => :json}

@alanguerin

It appears this is still an issue. Whilst trying to connect to Facebook, we were getting a OAuth2::Error containing just the string "access_token=CAAJfEQVqCnsBABOGdk2O9fowUC43br3u59r0e[...]&expires= 5182122".

We used @kyletns's solution to resolve it for now.
(@acvwilson's solution caused issues when making Open Graph requests.)

@nandinga

Same issue here. @kyletns solution did the trick for me.

@thmzlt
thmzlt commented Sep 30, 2014

There is no need to overwrite or add a new parser. The library comes with a bult-in parser for query string responses:

client.auth_code.get_token(auth_code, redirect_uri: redirect_uri, parse: :query)

The problem is Facebook returning text/plain for the content-type header when it should be application/x-www-form-urlencoded. Here are the relevant lines.

@nandinga

Right @thmzlt, just tested and works perfectly. Thx!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment