RubyGem: OAuthSimple 0.1.0.pre を公開しました
Ruby でクライアント側の OAuth 認証 (OAuth 1.0) を使おうとすると Ruby OAuth gem とかを使うことになると思うんですが、たいていの OAuth ライブラリって気軽さに欠けるような気がするんですよね。 OAuth 認証をばりばり使うような場面ならライブラリの使い方を学習するべきだと思いますが、「ちょっと Twitter の API を叩きたい」 というような場合にはもっと手軽に使えるものが欲しいですよね。 (もしかしたら既にあるのかな。。 )
というわけで Net::HTTP クラス に OAuth 認証の機能を加えたサブクラス OAuthSimple::HTTP を含むライブラリを作りました。 まだ機能的には完全じゃないですけど個人的に使うにはまあいいかなって感じなので pre 版として公開しました。
動作環境とインストール方法
Ruby 1.9.3 で使えることは確認しました。 1.8 系だと使えません。
インストールは gem コマンドを使って行うことができます。
$ gem install oauth_simple --pre
まだ pre 版なので --pre オプションが必要です。
OAuthSimple::HTTP の使い方
OAuthSimple::HTTP クラスは Net::HTTP クラスのサブクラスで、OAuth 認証をサポートします。 OAuthSimple::HTTP オブジェクトを生成した後に、use_oauth メソッドを使って OAuth 認証機能を使うことを指定し、set_oauth_client_credentials メソッドなどを使って OAuth 認証に必要な設定を行います。 その後は Net::HTTP オブジェクトを使うときと同じようにリクエストを投げると、勝手に OAuth 認証してくれます (現在は Authorization Header にプロトコルパラメータを付けてリクエストを投げるようになっています)。
以下に Twitter API を使う例を示します。 (Twitter の API については REST API Resources | Twitter Developers を見てください。)
require 'oauth_simple' # OAuth の client credentials と user credentials client_credentials = [ 'YOUR_CONSUMER_KEY', 'YOUR_CONSUMER_SECRET', ] token_credentials = [ 'YOUR_ACCESS_TOKEN', 'YOUR_ACCESS_TOKEN_SECRET', ] # OAuthSimple::HTTP は Net::HTTP のサブクラスで、Net::HTTP と同じようにインスタンス化できます http = OAuthSimple::HTTP.new( 'api.twitter.com' ) # OAuth 認証に関する設定を行います http.use_oauth = true # OAuth 認証を使うようにする http.set_oauth_client_credentials( *client_credentials ) # Client credentials を設定 http.set_oauth_user_credentials( *token_credentials ) # Token credentials を設定 http.set_oauth_signature_method( 'HMAC-SHA1' ) # Signature メソッドの設定 # 現在は 'HMAC-SHA1' にのみ対応 # 後は Net::HTTP オブジェクトを使用する場合と同じようにリクエストを投げます # 自動的に OAuth 認証を行ってくれます http.start do |http| path = '/1/statuses/mentions.json' http.request_get( path ) do |res| if res.code == '200' $stdout << res.body << "\n" # 実際は res.body を JSON 文字列としてパースして情報を取り出す else $stderr << "error\n" p res.body end end end
上のような方法だと OAuthSimple::HTTP オブジェクトを生成するごとに OAuth のパラメータ設定をしなければいけないという問題があります。 そこで、以下のように OAuthSimple::HTTP クラスのサブクラスを生成し、デフォルトの OAuth パラメータを持たせることができるようにもなっています。
require 'oauth_simple' # OAuth の client credentials と user credentials client_credentials = [ 'YOUR_CONSUMER_KEY', 'YOUR_CONSUMER_SECRET', ] token_credentials = [ 'YOUR_ACCESS_TOKEN', 'YOUR_ACCESS_TOKEN_SECRET', ] # OAuth 機能をもつ Net::HTTP のサブクラス (OAuthSimple::HTTP) # をサブクラス化して, デフォルトの OAuth パラメータを持たせる MyHTTP = OAuthSimple::HTTP.create_subclass_with_default_oauth_params() MyHTTP.set_default_oauth_client_credentials( *client_credentials ) # デフォルトの Client credentials を設定 MyHTTP.set_default_oauth_user_credentials( *token_credentials ) # デフォルトの Token credentials を設定 MyHTTP.set_default_oauth_signature_method( 'HMAC-SHA1' ) # デフォルトの Signature メソッドの設定 # 現在は 'HMAC-SHA1' にのみ対応 # 後は, 上で生成した MyHTTP を Net::HTTP と同じように使ってリクエストを投げます http = MyHTTP.new( 'api.twitter.com' ) http.start do |http| path = '/1/statuses/mentions.json' http.request_get( path ) do |res| if res.code == '200' $stdout << res.body << "\n" # 実際は res.body を JSON 文字列としてパースして情報を取り出す else $stderr << "error\n" p res.body end end end
どういう場合に使えるか
上で見たように、OAuth のパラメータさえ与えてしまえば後は Net::HTTP と同じように使えるので、書き捨てのスクリプトでちょっと OAuth 認証が必要な API を叩きたい、という場合などに便利だと思います。
不完全です
pre 版ってことからもわかるように不完全で、例えば対応している signature メソッドは HMAC-SHA1 だけであるとか、request_oauth_temp_credentials と request_oauth_token_credentials が POST メソッドにしか対応してないとか、OAuth パラメータをサーバーに渡す方法として authorization header の値として渡す方法しかサポートしてないとか、そういう問題があります。 そのうち対応したいなーとは思いつつ自分が使う分には困ってないのでいつになるやら、って感じです。 改造したい人は github のコードを適当にいじってください。
あんまり設計が綺麗じゃないので設計に関しての助言なども頂けると嬉しいです。
付録: Token Credentials の取得
Twitter に関して言えば、現在は My applications | Twitter Developers でアプリケーションの登録をすれば自分の Token credentials (access token と access token secret) が表示されるので、それをそのまま使えばよいです。
しかし、自分で Token credentials を取得しないといけない web サービスもあると思います。 そういうときには
OAuthSimple#request_oauth_temp_credentials メソッドと OAuthSimple#request_oauth_token_credentials メソッドが使用できます。
# coding: UTF-8 require 'net/https' # if you use ssl require 'oauth_simple' # OAuthSimple::HTTP is a subclass of Net::HTTP http = OAuthSimple::HTTP.new( 'api.twitter.com', 443 ) # SSL setting http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_PEER # 認証モードをセット # OAuth setting (this feature is provided by OAuthSimple::HTTP) http.use_oauth = true http.set_oauth_client_credentials( 'YOUR_CLIENT_CREDENTIALS', 'YOUR_CLIENT_SECRET' ) http.set_oauth_signature_method( 'HMAC-SHA1' ) # at this time, only 'HMAC-SHA1' is supported # connection start http.start() do |http| # Temporary Credentials を取得 (取得した credentials は自動的に http オブジェクトにセットされる) token, secret = http.request_oauth_temp_credentials( '/oauth/request_token', 'oob' ) do |res_failed| # ステータスコード 200 以外が返ってきたらこのブロックがよばれる raise res_failed.body end # リソースオーナーによる認証 (利用者に認証ページで認証してもらい, verifier を入力してもらう) puts "https://api.twitter.com/oauth/authorize?oauth_token=#{OAuthSimple::HelperFunctions.enc_perenc(token)} にてアプリケーションを認証し, " + 'verifier を入力してください' $stdout << 'verifier : ' verifier = $stdin.gets.chomp # Token Credentials を取得 (取得した credentials は自動的に http オブジェクトにセットされる) token, secret = http.request_oauth_token_credentials( '/oauth/access_token', verifier ) do |res_failed| # ステータスコード 200 以外が返ってきたらこのブロックがよばれる raise res_failed.body end # 変数 token と secret の中に Token credentials が入っているので, 保存が必要なら保存する # あとは先の例と同じように認証が必要なリソースにアクセスして使用する http.request_get( '/1/statuses/home_timeline.json?include_entities=true' ) do |res| # ... 省略 ... end end