トップ «前の日記(2007-12-03 (月)) 最新 次の日記(2007-12-06 (木))»  

まちゅダイアリー


2007-12-05 (水)

OAuth Core 1.0 がリリース, "Your Valet Key for the Web"

開催中の Internet Identity Workshop で、 OAuth が正式に公開されたみたい。

アナウンスでは、 OAuth のキャッチフレーズを紹介している。

summarized as “your valet key for the web,”

「バレットキー」って何だ?と思って調べてみた。 どうやら、ホテルでボーイに預けるための車の鍵らしい。

メインキーはもちろん全てのカギ穴に有効ですが、バレットキーは運転席ドアの開錠とエンジン始動しかできません。つまりレストランやホテルで車を預けて駐車場に止めておいてもらう(バレットパーキング)時に使うためのカギで、貴重品をグローブボックスやトランクに入れておいても開けられないようにしてあるわけです。

うまい例えだなぁ。 OAuth は、WebAPI のアクセス制御に使える OAuth という仕様で書いたように、パスワードを教えずに第三者にTwitterの発言などを更新させたい場合に使う。 車のマスターキーが Twitter のパスワードとすれば、ホテルのボーイに渡すバレットキー(トランクは開けられない)が OAuth のトークンになるってことか。

あとは Flickr や Twitter がいつ対応するか。 Twitter はトークンの取得はできたけど、トークンを使った発言の更新ができなかったんだよね。

Tags: OAuth

OAuth の Rails 実装 (oauth-plugin, oauth4r) を使ってみた

1.0 のリリース記念って訳じゃないけど、 OAuth の Rails 実装を試してみた。 ちょっと調べたところ、 OAuth の Rails 実装は2種類あるらしい。

軽く両者を比較してみたところ、 oauth-plugin は機能が少ないけど使いやすそう。 oauth4r は機能は多いけど完成度はまだまだといった感じ。付属のサンプルだけなら簡単に動きそうだけどね。

今回は oauth-plugin を使ったときの記録。

インストール (Provider)

基本的に How to turn your rails site into an OAuth Provider に書かれている通りに進める。

$ sudo gem install oauth
$ rails -d sqlite3 provider
$ cd provider
$ ./script/plugin install http://oauth-plugin.googlecode.com/svn/trunk/oauth_plugin

また、 oauth-plugin は Rails2.0 じゃないと動かない。 なので、 oauth4r に付属していた rails_rc1 ディレクトリ (Rails2.0が入ってる) をアプリの vender ディレクトリに突っ込む。 こうすれば gem でインストールした Rails (1.2.6) よりも優先して読み込んでくれる。

ユーザ管理機能の作成 (Provider)

OAuth の Provider は、 Twitter や Flickr のようにユーザのつぶやきや写真を管理する役割になる。 そのために、 Provider にユーザ管理機能を作る。 説明では acts_as_authenticated, restful_authentication, restful_openid_authentication などのプラグインを使ってねって書かれてあるけど、せっかくなので こないだ試した openid_login_generator を使うことにした。

$ ./script/generate openid_login Account
$ script/generate model user openid_url:string
$ rake db:migrate

ただ、 openid_login_generator は Rails2.0 ではそのまま動かなかったので、修正を加えている。

  • app/controllers/account_controller.rb にて @request, @session を request, session に修正する。
  • app/models/user.rb の find_first を find_by_openid_url に修正する。
Index: app/models/user.rb
===================================================================
--- app/models/user.rb  (revision 94)
+++ app/models/user.rb  (working copy)
@@ -5,7 +5,7 @@
   has_many :tokens, :class_name=>"OauthToken",:order=>"authorized_at desc",:include=>[:client_application]

   def self.get(openid_url)
-    find_first(["openid_url = ?", openid_url])
+    find_by_openid_url(openid_url)
   end

これで Rails2.0 でも openid_login_generator が動くようになった。

OAuth 機能の作成 (Provider)

下準備が終わったので、いよいよ AOuth の Provider の機能を作る。 といっても、ジェネレータを呼び出すだけ。

$ script/generate oauth_provider

結構たくさんのファイルが追加される。 モデルだけでも5つある。

  • app/models/client_application.rb
  • app/models/oauth_token.rb
  • app/models/request_token.rb
  • app/models/access_token.rb
  • app/models/oauth_nonce.rb

一方、コントローラは1つだけだった。

  • app/controllers/oauth_controller.rb

これらのファイルは特に修正しない。 代わりに既存の User クラスを修正する。

class User < ActiveRecord::Base
  has_many :client_applications
  has_many :tokens, :class_name=>"OauthToken",:order=>"authorized_at desc",:include=>[:client_application]

ユーザと Consumer の登録 (Provider)

Web ブラウザから http://server.example.com/oauth/ にアクセスすると、ログイン画面へと転送される。

OAuth Sample (1)

ID とパスワードを入力(今回は OpenID を使ったので OpenID のアカウント名を入力)してログインすると、 Consumer 一覧の画面が表示される。

OAuth Sample (2)

ここで新しい Consumer を登録するようになってる。ちょっと本格的。 今回はまだ Consumer までは作らないので、内容は適当に入れる。

OAuth Sample (3)

すると、 OAuth で使う Consumer Key と Consumer Secret が発行される。 この辺は Twitter の時と同じ。

OAuth Sample (4)

irb から OAuth サーバにアクセスする (Consumer)

まだ Consumer 側のアプリは作っていないので、 irb を使って OAuth のトークンを取得してみる。

require 'oauth'

consumer = OAuth::Consumer.new(
  :consumer_key => 'HeVnVSLpCpodiRZ4Pbqwlg',
  :consumer_secret => 'zxv4s7rM7v4bYG0PfT8MDxGUR4SidtESaQhTxBmqOk',
  :site => 'http://axela.machu.jp:5000',
  :request_token_path => '/oauth/request_token', 
  :access_token_path => '/oauth/access_token', 
  :authorize_path => '/oauth/authorize'
)

initialize で渡す引数は、さっき OAuth の Provider で表示されてた情報になる。

req_token = consumer.get_request_token
req_token.authorize_url
=> "http://axela.machu.jp:5000/oauth/authorize?oauth_token=BtJ18E7RgMysQ9cfc0bGDQ"

get_request_token メソッドを呼んで、 Provider から Request Token を取得する。 authorize_url メソッドで、ユーザのリダイレクト先が取得できる。

Web ブラウザでアクセスすると、 Consumer にトークンを渡してよいかどうかの確認画面が表示される。

OAuth Sample (5)

再び irb へ戻る。 Request Token から Access Token を取得する。 以降は Access Token の GET メソッドで、 Provider 上のユーザ情報を取得する。今回はまだ Provider 上にアプリを作ってないので、データも取ってこれないけど。

access_token = req_token.get_access_token
access_token.get('/photo/123456')

ここまでのまとめ

  • oauth-plugin を使えば OAuth のプロバイダ側の実装は簡単に出来そう
  • でも生成されるクラスが多いので、ちゃんと内容を把握しないと危険
  • Consumer 側はこれから
Tags: OAuth