RAILS PRESS RUBY on RAILS, it’s DRY and COOL …

RSS Feed

RAILS PRESS RSS

Tag Cloud

はてなブックマーク - railspress.matake.jp の注目エントリー
象形文字くさび形文字ミイラそろばんの玉そろばんコーラン占いの板?象牙大英博物館

Posted on
2010/10/24

Tags
OAuth, Yahoo, ノウハウ

0 Comment

この記事をはてなブックマークに登録 この記事のはてなブックマーク数 この記事を livedoor クリップに登録この記事の livedoor クリップ数 このエントリを del.icio.us に追加
ブックマークに追加する

Using OAuth Gem for Yahoo! OAuth

For Yahoo! OAuth, you need to handle OAuth Session Extension.
It is much harder than normal OAuth 1.0, normal one is enough hard though :(

I've talked with pelle, OAuth Gem developer and the guy who named Yahoo!'s OAuth "YAuth", about handling Yahoo! specific extension in OAuth Gem, and reached a conclusion not to do so.

Instead to support YAuth, I overwrote some OAuth gem classes.

First, you need to add "session_handle", "expires_in" and "authorization_expires_in" in the OAuth AccessToken class.
(Yes, you also need migration to add those columns to DB.)

LANG : RUBY
  1. # yahoo specific access token
  2. class OAuth::AccessToken::Yahoo <OAuth::AccessToken
  3.   # :external_user_id seems to be Y! original attribute
  4.   attr_accessor :external_user_id, :session_handle, :expires_in, :authorization_expires_in
  5.   def initialize(consumer, token, secret, options = {})
  6.     super(consumer, token, secret)
  7.     @external_user_id         = options[:external_user_id]
  8.     @session_handle           = options[:session_handle]
  9.     @expires_in               = options[:expires_in]
  10.     @authorization_expires_in = options[:authorization_expires_in]
  11.   end
  12. end

Below is basically same changes for RequestToken class.

LANG : RUBY
  1. # yahoo specific request token
  2. class OAuth::RequestToken::Yahoo <OAuth::RequestToken
  3.   def get_access_token(options={})
  4.     response = consumer.token_request(consumer.http_method, consumer.access_token_path, self, options)
  5.     access_token = OAuth::AccessToken::Yahoo.new(
  6.       consumer,
  7.       response[:oauth_token],
  8.       response[:oauth_token_secret],
  9.       {
  10.         :external_user_id         => response[:xoauth_yahoo_guid],
  11.         :session_handle           => response[:oauth_session_handle],
  12.         :expires_in               => response[:oauth_expires_in],
  13.         :authorization_expires_in => response[:oauth_authorization_expires_in]
  14.       }
  15.     )
  16.   end
  17. end

And this is the actual Rails model using those.

LANG : RUBY
  1. # Yahoo! OAuthToken
  2. class YAuthToken <ActiveRecord::Base
  3.  
  4.   class Exception <StandardError; end
  5.  
  6.   def to_access_token
  7.     refresh! if expired?
  8.     OAuth::AccessToken::Yahoo.new(self.class.consumer_digested, self.token, self.secret)
  9.   end
  10.  
  11.   def self.establish_access_token!(user, token, secret = "", oauth_verifier = "")
  12.     request_token = OAuth::RequestToken::Yahoo.new(self.consumer, token, secret)
  13.     access_token  = request_token.get_access_token(:oauth_verifier => oauth_verifier)
  14.     access_token  = self.new(
  15.       :user_id                  => user.id,
  16.       :token                    => access_token.token,
  17.       :secret                   => access_token.secret,
  18.       :external_user_id         => access_token.external_user_id,
  19.       :session_handle           => access_token.session_handle,
  20.       :expires_in               => access_token.expires_in,
  21.       :authorization_expires_in => access_token.authorization_expires_in
  22.     )
  23.     access_token.save!
  24.   rescue Net::HTTPServerException => e
  25.     raise YAuthToken::Exception.new(e.message)
  26.   end
  27.  
  28.   def self.consumer
  29.     @consumer ||= OAuth::Consumer.new(
  30.       self.config[:oauth_consumer_key], self.config[:oauth_consumer_secret],
  31.       {
  32.         :site               => 'https://api.login.yahoo.com',
  33.         :scheme             => :body,
  34.         :request_token_path => '/oauth/v2/get_request_token',
  35.         :authorize_path     => '/oauth/v2/request_auth',
  36.         :access_token_path  => '/oauth/v2/get_token'
  37.        }
  38.     )
  39.   end
  40.  
  41.   def self.consumer_digested
  42.     @consumer_digested ||= OAuth::Consumer.new(
  43.       self.config[:oauth_consumer_key], self.config[:oauth_consumer_secret],
  44.       {
  45.         :site  => 'http://social.yahooapis.com',
  46.         :realm => 'yahooapis.com'
  47.       }
  48.     )
  49.   end
  50.  
  51.   def self.config
  52.     @config ||= YAML.load_file("#{SMART_CORE_ROOT}/config/yahoo.yml")[RAILS_ENV].symbolize_keys
  53.   rescue StandardError => e
  54.     raise StandardError.new("config/yahoo.yml could not be loaded.")
  55.   end
  56.  
  57.   private
  58.  
  59.   # Yahoo! requres access_token refresh every hour
  60.   def expired?
  61.     if self.created_at <= Time.now - self.authorization_expires_in
  62.       raise YAuthToken::Exception.new('Yahoo! OAuth token are expired.')
  63.     else
  64.       self.updated_at <= Time.now - self.expires_in
  65.     end
  66.   end
  67.  
  68.   def refresh!
  69.     request_token = OAuth::RequestToken::Yahoo.new(self.class.consumer, self.token, self.secret)
  70.     access_token  = request_token.get_access_token(:oauth_session_handle => self.session_handle)
  71.     self.token          = access_token.token
  72.     self.secret         = access_token.secret
  73.     self.session_handle = access_token.session_handle
  74.     self.expires_in     = access_token.expires_in
  75.     self.save!
  76.   rescue Net::HTTPServerException => e
  77.     raise YAuthToken::Exception.new(e.message)
  78.   end
  79.  
  80. end

This model checks expiry of access token and authorization, and refresh the token when token is expired, but authorization is still available.
When you got an 401 response when refreshing the access token, think the authorization is manually revoked by user and not refreshable anymore.

Posted on
2008/12/27

Tags
OAuth, Yahoo, ノウハウ

0 Comment

この記事をはてなブックマークに登録 この記事のはてなブックマーク数 この記事を livedoor クリップに登録この記事の livedoor クリップ数 このエントリを del.icio.us に追加
ブックマークに追加する

ruby-oauth で Yahoo! OAuth を使う方法

ruby-oauth で Yahoo! OAuth を使おうとしてだいぶはまったので、対応方法をメモ。

まずは oauth_parameter のうち、値が空のものは送らないようにしないと行けないようです。これは Yahoo! 側の問題かな?この問題を解決するには、OAuth::Client::Helper をオーバーライドします。

LANG : RUBY
  1. # Yahoo! Hacks (for OAuth2.1)
  2. class OAuth::Client::Helper
  3.   def oauth_parameters
  4.     { 'oauth_consumer_key'     => options[:consumer].key,
  5.       'oauth_token'            => options[:token] ? options[:token].token : '',
  6.       'oauth_signature_method' => options[:signature_method],
  7.       'oauth_session_handle'   => options[:oauth_session_handle] ? options[:oauth_session_handle] : '',
  8.       'oauth_timestamp'        => timestamp,
  9.       'oauth_nonce'            => nonce,
  10.       'oauth_version'          => '1.0' }.reject { |k,v| v == "" }
  11.   end
  12. end

次に、Yahoo! OAuth では1時間ごとに token を再発行したり、その際に session_handle を使ったりするので、ruby-oauth の OAuth::AccessToken と OAuth::RequestToken をこれらの属性に対応させる必要があります。

» このエントリーには続きがあります。続きを読む »

Posted on
2008/12/23

Tags
API, Gem, OAuth, iKnow!, リリース

2 Comments

この記事をはてなブックマークに登録 この記事のはてなブックマーク数 この記事を livedoor クリップに登録この記事の livedoor クリップ数 このエントリを del.icio.us に追加
ブックマークに追加する

iKnow! gem 0.2.2

version 0.4.0 - version 0.1.1 までの更新履歴はこちら。
iKnow! gem version 0.1.1 - 京の路
iKnow! gem version up - OAuth & Basic認証 - 京の路

version 0.2.2 となり、ようやくこちらのブログでも発表できるレベルになりました。version 0.2.2 では、OAuth / Basic 認証のサポート、すべての要認証 API Call のサポートが追加されています。

OAuth / Basic 認証は同じインタフェースで使えます。Iknow::Auth に username と password を指定すれば Basic 認証、token と secret を指定すれば OAuth を使います。

LANG : RUBY
  1. iknow_auth = case auth_mode
  2.   when :oauth
  3.     Iknow::Auth.new(
  4.       :token => OAUTH_ACCESS_TOKEN,
  5.       :secret => OAUTH_ACCESS_TOKEN_SECRET
  6.     )
  7.   when :basic_auth
  8.     Iknow::Auth.new(
  9.       :username => IKNOW_USERNAME,
  10.       :password => IKNOW_PASSWORD
  11.     )
  12. end

あとは、要認証 API Call の第一引数に Iknow::Auth のインスタンスを渡してください。(※ 12月23日現在、OAuth の DELETE 系 Call がエラーになりますが、これは iKnow! API 側の問題です)

» このエントリーには続きがあります。続きを読む »

« 前の3件