OAuth Echo認証のRails Gemを作ってみた

Twitterの各ツイートに「いいね!」などのデータをつけるようなサービスを考えていて、ちょっと試作していたところで、そのAPIの認証にはOAuth Echoという方法がよさそうだということがわかりました。
そこで、その試作から認証部分を切り出して、OAuth Echo認証のサーバ側をRailsで使うためのGemを作ってみました。
ちょうど、@yusukeyさんが「第2.1回 Twitter API 勉強会 @東京」を開催されるということで、LTで話してきました。

OAuth Echo の概略

OAuthについてはほとんど説明していないので、詳しくはググってください(すみません)。OAuth 1.0はそこそこ複雑なのですが、OAuth Echoのしくみは簡単です。
Twitterには、使用するのに認証が必要な verify_credentials というAPIがあります。クライアントからこのAPIをリクエストするとき、このようにOAuthのAuthorizationヘッダをつけます(ヘッダを生成するためのsimple_oauthなどのライブラリを使うと楽です)。

GET /1/account/verify_credentials.json HTTP/1.1
Host: api.twitter.com
Authorization: OAuth oauth_consumer_key="GDdmIQH6jhtmLUypg82g",
oauth_nonce="oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y",
oauth_signature="U1obTfE7Rs9J1kafTGwufLJdspo%3D",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1272325550",
oauth_token="819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw",
oauth_version="1.0"

クライアントがTwitPicに画像をアップロードするためには、リクエストをこのように変えるだけです。

POST /2/upload.json HTTP/1.1
Host: api.twitpic.com
X-Auth-Service-Provider: https://api.twitter.com/1/account/verify_credentials.json
X-Verify-Credentials-Authorization: OAuth realm="http://api.twitter.com/",
oauth_consumer_key="GDdmIQH6jhtmLUypg82g",
oauth_nonce="oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y",
oauth_signature="U1obTfE7Rs9J1kafTGwufLJdspo%3D",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1272325550",
oauth_token="819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw",
oauth_version="1.0"

ヘッダ部分は、AuthorizationをX-Verify-Credentials-Authorizationに変えるだけで、ほぼ同じです。
TwitPicはこれを受け取って、Authorizationヘッダに戻し、そのままTwitterにリクエストします。Twitterからは認証の結果が返ってくるので、OK(200)ならばアップロードを許可するというしくみです。

エッセンス

Railsには、HTTP Basic認証を簡単にかけられる機能があります。

class PostsController < ApplicationController
  http_basic_authenticate_with :name => "tkawa", :password => "secret"

  def index
    render :json => { :message => "Limited Access" }
  end
  ...
end

http_basic_authenticate_withというメソッドを呼ぶだけです。これは便利だね、ってことで、この部分のコード(ActionController::HttpAuthentication::Basic)をかなり参考にして、似たインターフェイスでOAuth Echo認証をできるようにしました。

class PostsController < ApplicationController
  oauth_echo_authenticate_with :twitter

  def index
    render :json => { :message => "Limited Access", :user => @current_user }
  end
  ...
end

oauth_echo_authenticate_withというメソッドを呼ぶだけです。引数にはService Providerを指定しますが、現状:twitterにしか対応していません。
認証結果を自分でコントロールするために、before_filter内で使用できるメソッドも用意しています。

ソース

コード自体は60行ぐらいしかないごく短いもので、Gemを作る練習をしてみた、という感じです。見よう見まねで、Gemはこれでいいのかまだよくわかってません…。

Ustream

時間がある方は、当日のLTのUstream録画がありますので、よければそちらもごらんください。(よけいわかりにくいかもしれないので、ご意見ご指摘希望…)

@yusukeyさん、みなさんありがとうございました。

余談


みんな使ってるからということで、深く考えずSlideShareを使ったんだけど、どうやらSpeaker Deckがいいらしいという話も。どうなんでしょ。
一応Speaker Deckにも上げてみた。
OAuth Echo の Rails Gem - Speaker Deck