ゼロから学ぶOAuth

第3回 OAuth Consumerの実装(応用 : smart.fm APIおよびGoogle Data APIsの利用)

この記事を読むのに必要な時間:およそ 5.5 分

OAuth::RequestTokenの利用

OAuth::RequestTokenはRequest Tokenを保存するクラスです。OAuth::RequestTokenインスタンスを取得するには,OAuth::Consumer#get_request_tokenを利用します。Google Data APIsのscopeパラメータ,smart.fm APIのAPI Keyなどはget_request_tokenの第2引数(以下のrequired_parameters)で指定します。

@request_token = @consumer.get_request_token({}, required_parameters)

この時点で@request_tokenは未認可ですので,ユーザをauthorize_urlにリダイレクトさせます。またtokenとsecretは後で利用しますので,sessionに保存しておきます。

このauthorize_urlにはCallback URLを含めることもできます。Callback URLを利用する場合は,authorize_urlにoauth_callbackというURLパラメータを付加することになります。通常Service ProviderではConsumer登録時にデフォルトCallback URLを登録させますが,oauth_callbackが指定されていればそちらを優先します。

session[:request_token] = @request_token.token
session[:request_token_secret] = @request_token.secret
redirect_to @request_token.authorize_url + "?oauth_callback=#{callback_url}"

ユーザがRequest Tokenに認可を与えた後Request TokenとAccess Tokenを交換する為にも,OAuth::RequestTokenを用います。

request_token = OAuth::RequestToken.new(
  consumer,
  session[:request_token],
  session[:request_token_secret]
)

@access_token = request_token.get_access_token

OAuth::AccessTokenの利用

Access Tokenが必要なアクセスは,OAuth::AccessTokenインスタンスを経由して行うことになります。GET / POST / PUT / DELETEは,それぞれ以下のように行えます。ちなみに第2回(http://gihyo.jp/dev/feature/01/oauth/0002)最後のサンプルコードではPOSTを用いました。

access_token = OAuth::AccessToken.new(
  consumer,
  stored_token,
  stored_token_secret
)

# GET
access_token.get(PATH_OR_URL)
access_token.get(PATH_OR_URL, HEADER)

# POST
access_token.post(PATH_OR_URL, BODY)
access_token.post(PATH_OR_URL, BODY, HEADER)

# PUT
access_token.put(PATH_OR_URL, BODY)
access_token.put(PATH_OR_URL, BODY, HEADER)

# DELETE
access_token.delete(PATH_OR_URL)
access_token.delete(PATH_OR_URL, HEADER)

smart.fm APIとGoogle Contacts Data APIを利用する

さて,ここまでで紹介した使い方で,OAuth Consumerとして必要なことはおおよそつかんでいただいたはずです。Consumer実装の最後では,smart.fm APIとGoogle Data APIsを利用する際に注意すべきことを述べておきます。

smart.fm APIの利用

smart.fm OAuthを利用する際に注意すべき点として,Authorize URLがRequest Token URLとAccess Token URLとは別ドメインになっています。またsmart.fmのOAuthを利用するには,Consumer Keyの他にAPI Keyが必要です。そのため前述のget_request_tokenメソッドの引数のrequired_parametersの部分にapi_keyを指定する必要があります。

required_parameters = {api_key => SMARTFM_API_KEY}
@consumer.get_request_token({}, required_parameters)

またAPI KeyはAccess Token取得時にも必要ですが,ruby-oauth ver.0.3.1ではget_access_tokenでAPI Keyを渡すができないため,第2回(http://gihyo.jp/dev/feature/01/oauth/0002)で紹介したサンプルアプリケーションでは以下のようにパッチを当てています。get_access_tokenでのService Provider独自パラメータの利用は,ruby-oauthの次期バージョンでサポートされる予定ですが,それまではこのようなパッチを当てて対応するしか無いでしょう。

# Hacks
# Support params in get_access_token request for smart.fm API's api_key
class OAuth::RequestToken
  def get_access_token_with_args(options = {}, *args)
    access_token_url = consumer.access_token_url? ? consumer.access_token_url : consumer.access_token_path
    response = consumer.token_request(consumer.http_method, access_token_url, self, options, *args)
    OAuth::AccessToken.new(consumer, response[:oauth_token], response[:oauth_token_secret])
  end
  alias_method :get_access_token_without_args, :get_access_token
  alias_method :get_access_token, :get_access_token_with_args
end

またAccess Tokenを取得した後,smart.fm APIを利用するには,smart.fm gemを利用するのが一番簡単だと思います。

gem install smartfm

このgemは現在smart.fm APIで提供されているほぼ全ての機能をサポートしています。また新しい機能がリリースされた場合にも,なるべく早く対応していきます。smart.fm gemでは独自のSmartfm::AuthクラスでOAuthサポートを行っていますが,もちろん内部的にはOAuth::ConsumerとOAuth::AccessTokenを使っています。

認可が必要なAPIは,以下のようにSmartfm::Authのインスタンスを引数に渡して利用します。⁠Basic Authも利用可能)

require 'rubygems'
require 'smartfm'
require 'oauth/consumer'

Smartfm::Config.init do |conf|
  conf.api_key               = YOUR_API_KEY
  conf.oauth_consumer_key    = YOUR_OAUTH_CONSUMER_KEY
  conf.oauth_consumer_secret = YOUR_OAUTH_CONSUMER_SECRET
end

auth = Smartfm::Auth.new(
  :token => OAUTH_ACCESS_TOKEN,
  :secret => OAUTH_ACCESS_TOKEN_SECRET
)

## BASIC AUTH
# auth = Smartfm::Auth.new(
#   :username => USERNAME,
#   :password => PASSWORD
# )

# List API
@list = Smartfm::List.create(
  auth,
  :title => 'smart.fm gem test',
  :description => 'A list for smart.fm gem test'
)
@list.add_item(auth, Smartfm::Item.find(437525))

# Item API
@item = Smartfm::Item.create(
  auth,
  :cue => {
    :text           => 'hello world!',
    :language       => 'en',
    :part_of_speech => 'E'
  },
  :response => {
    :text     => 'ハローワールド!',
    :language => 'ja'
  }
)
@item.add_image(auth, 'http://farm4.static.flickr.com/3276/3102381796_a33c1ffdf1.jpg')
@item.add_sound(auth, 'http://matake.jp/download/hello_world.mp3')
@item.add_tags(auth, 'sample', 'programming')

# Sentence API
@sentence = Smartfm::Sentence.create(
  auth,
  :text => 'Hello World!',
  :item => Smartfm::Item.matching('hello world').first
)
@sentence.add_image(auth, 'http://farm4.static.flickr.com/3276/3102381796_a33c1ffdf1.jpg')
@sentence.add_sound(auth, 'http://matake.jp/download/hello_world.mp3')

その他の認可の必要ないAPIの利用方法はsmart.fm gemのexamples/pure_ruby.rbをご覧ください。

著者プロフィール

真武信和(またけのぶかず)

Cerego Japan Inc.で働くWebエンジニア。

smart.fmで外部APIとの連携機能(OAuth Consumer)の開発に携わるほか、smart.fm API(OAuth Service Provider)の開発にも携わっている。

URL:
http://matake.jp/
http://smart.fm/users/matake