Ruby OAuth 噩梦:使用联系人 API

发布于 2024-09-27 05:47:07 字数 2242 浏览 2 评论 0原文

在过去的几天里,我一直在绞尽脑汁地支持在我的 Rails 3 应用程序中向 Google Contacts API 添加联系人的功能。尽管有很多错误的开始,我终于通过使用 Ruby OAuth gem 并按照此处的教程取得了一些进展:http://everburning.com/news/google-analytics-oauth-and-ruby-oh-my/

当我在控制台中遵循此操作时,我会更进一步比我在 Rails 应用程序中所做的要多。我可以创建一个访问令牌,使用联系人 API 的特定范围对 Google 的服务进行身份验证,然后应用 oauth_verifier 令牌来获取访问令牌。但是当需要推送数据时,我收到此错误:

response = at.post("https://www.google.com/m8/feeds/contacts/default/full", gdata)
 => #<Net::HTTPUnauthorized 401 Unknown authorization header readbody=true> 

“readbody=true”标头来自哪里,我将如何摆脱它?

但在 Rails 应用程序中情况更糟。我有一个控制器操作(“googlecontacts”),它创建请求令牌并引导用户使用 Google 进行身份验证站点:

def googlecontacts

@card = Card.find_by_short_link(params[:id])

@consumer = OAuth::Consumer.new( 
  'anonymous', 
  'anonymous', 
  { 
    :site => 'https://www.google.com', 
    :request_token_path => '/accounts/OAuthGetRequestToken', 
    :access_token_path => '/accounts/OAuthGetAccessToken', 
    :authorize_path => '/accounts/OAuthAuthorizeToken', 
    :signature_method => 'HMAC-SHA1',
    :oauth_version => '1.0'
  })

@request_token = @consumer.get_request_token(
  {:oauth_callback => 'http://monkey.dev/cards/google_auth?redir='[email protected]_link}, 
  {:scope => "https://www.google.com/m8/feeds/"}
)

session[:request_token] = @request_token

redirect_to @request_token.authorize_url

end

这似乎有效;我得到一个工作请求令牌对象,并且用户被转发到 Google 服务进行身份验证。回调 URL(“google_auth”)应使用 oauth_verifier 令牌来创建访问令牌。这是控制器的开始部分:

def google_auth

   @access_token = session[:request_token].get_access_token(:oauth_verifier=>params[:oauth_verifier])

这就是它崩溃的地方。最后一行的错误是:

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]

但是其中的值 - session[:request_token] 和 params[:oauth_verifier] - 存在并在该操作中说明!我不明白这里的 nil 是什么。

所以我想我需要先解决第二个问题,但回答第一个问题也可以加分。 :-)

感谢您的阅读。

亚伦.

I've been spending the last few days banging my head against the wall on supporting the ability to add a contact to the Google Contacts API in my Rails 3 application. Despite many false starts, I've finally made some progress by employing the Ruby OAuth gem, and following the tutorial here: http://everburning.com/news/google-analytics-oauth-and-ruby-oh-my/

When I follow this in the console, I get further than I do in my Rails app. I can create an access token, authenticate against Google's service with the specific scope of the Contacts API, and apply the oauth_verifier token to get an access token. But when it comes time to push the data, I get this error:

response = at.post("https://www.google.com/m8/feeds/contacts/default/full", gdata)
 => #<Net::HTTPUnauthorized 401 Unknown authorization header readbody=true> 

Where does the "readbody=true" header come from, and how would I get rid of it?

But it's worse in the Rails app. I have one controller action ("googlecontacts") that creates the request token and leads the user to the authentication site with Google:

def googlecontacts

@card = Card.find_by_short_link(params[:id])

@consumer = OAuth::Consumer.new( 
  'anonymous', 
  'anonymous', 
  { 
    :site => 'https://www.google.com', 
    :request_token_path => '/accounts/OAuthGetRequestToken', 
    :access_token_path => '/accounts/OAuthGetAccessToken', 
    :authorize_path => '/accounts/OAuthAuthorizeToken', 
    :signature_method => 'HMAC-SHA1',
    :oauth_version => '1.0'
  })

@request_token = @consumer.get_request_token(
  {:oauth_callback => 'http://monkey.dev/cards/google_auth?redir='[email protected]_link}, 
  {:scope => "https://www.google.com/m8/feeds/"}
)

session[:request_token] = @request_token

redirect_to @request_token.authorize_url

end

This appears to work; I get a working request token object, and the user is forwarded to the Google service to authenticate. The callback URL ("google_auth") should take the oauth_verifier token to create an access token. Here's the beginning of the controller:

def google_auth

   @access_token = session[:request_token].get_access_token(:oauth_verifier=>params[:oauth_verifier])

And here's where it craps out. The error on that last line is:

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]

But the values that are in there -- the session[:request_token] and the params[:oauth_verifier] -- are present and accounted for in that action! I can't figure out what is nil here.

So I guess I need to figure out this second problem first, but bonus points for answering the first problem as well. :-)

Thanks for reading.

Aaron.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

乜一 2024-10-04 05:47:07

尝试使用字符串而不是符号设置/获取会话数据,即 session["request_token"],而不是 session[:request_token]。我知道我以前也遇到过这个问题。

Try setting/getting the session data with a string not symbol, i.e. session["request_token"], not session[:request_token]. I know I've had that issue before in the past.

时光匆匆的小流年 2024-10-04 05:47:07

未知授权标头通常意味着您的签名与您发送的内容不匹配。我不推荐 oauth gem。它充满了错误和奇怪的问题,并且无法正确转义某些参数。

Signet gem 是官方支持的 gem,用于在 Ruby 中访问 Google API。

以下是使用 Signet 实现此功能的方法:

require 'signet/oauth_1/client'
require 'addressable/uri'
card = Card.find_by_short_link(params[:id])
callback = Addressable::URI.parse('http://monkey.dev/cards/google_auth')
callback.query_values = {'redir' => card.short_link}

client = Signet::OAuth1::Client.new(
  :temporary_credential_uri =>
    'https://www.google.com/accounts/OAuthGetRequestToken',
  :authorization_uri =>
    'https://www.google.com/accounts/OAuthAuthorizeToken',
  :token_credential_uri =>
    'https://www.google.com/accounts/OAuthGetAccessToken',
  :client_credential_key => 'anonymous',
  :client_credential_secret => 'anonymous',
  :callback => callback
)

session[:temporary_credential] = (
  client.fetch_temporary_credential!(:additional_parameters => {
    :scope => 'https://www.google.com/m8/feeds/'
  })
)
redirect_to(client.authorization_uri)

Unknown authorization header typically means that your signature didn't match what you sent. I do not recommend the oauth gem. It's full of bugs and weird issues and it doesn't properly escape certain parameters.

The Signet gem is the officially supported gem for accessing Google APIs in Ruby.

Here's how you'd implement this with Signet:

require 'signet/oauth_1/client'
require 'addressable/uri'
card = Card.find_by_short_link(params[:id])
callback = Addressable::URI.parse('http://monkey.dev/cards/google_auth')
callback.query_values = {'redir' => card.short_link}

client = Signet::OAuth1::Client.new(
  :temporary_credential_uri =>
    'https://www.google.com/accounts/OAuthGetRequestToken',
  :authorization_uri =>
    'https://www.google.com/accounts/OAuthAuthorizeToken',
  :token_credential_uri =>
    'https://www.google.com/accounts/OAuthGetAccessToken',
  :client_credential_key => 'anonymous',
  :client_credential_secret => 'anonymous',
  :callback => callback
)

session[:temporary_credential] = (
  client.fetch_temporary_credential!(:additional_parameters => {
    :scope => 'https://www.google.com/m8/feeds/'
  })
)
redirect_to(client.authorization_uri)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文