RubyのoauthでSignature検証
なんかサンプルコードが見つからなかったので書いておく。
OAuth::Signitureというクラスが利用できる。
require 'oauth'
def verify(request)
consumer = OAuth::Consumer.new(
'SOME CONSUMER KEY', 'SOME CONSUMER SECRET',
:site => 'http://api.example.com'
)
headers = oauth_headers(request)
signature = OAuth::Signature.build(request) do
[headers['oauth_token_secret'], consumer.secret]
end
signature.verify
end
def oauth_headers
headers = {}
request.env['HTTP_AUTHORIZATION'].split(',').each{|item| k, v = item.split('='); headers[k.strip] = v.gsub(/"/, '')}
headers
end
OAuth::Signature.buildの部分は
signature = OAuth::Signature.build(request)
だったり
signature = OAuth::Signature.build(request) do
[nil, consumer.secret]
end
でよかったりすることもあると思いますよ。
コード解説
requestって何者
requestはRailsのコントローラ内で使えるものをそのまま渡せる。
Sinatraなどの場合もrequestという名前で定義されているものを基本そのまま渡せるが、以下のrequireが必要。
require 'oauth/request_proxy/rack_request'
requestは内部的にOAuth::RequestProxy::Baseのサブクラスに適宜変換される模様。
oauth_headersメソッド
oauth_headersメソッドはoauth_token_secretが取れなかったので作ったメソッド。
他のoauth_tokenなどの値はOAuth::RequestProxyを使うと取得できる。
request_proxy = OAuth::RequestProxy.proxy(request)
request_proxy.oauth_token
request_proxy.signature
などで取れるんだけど、なんでかoauth_token_secretは取れず。
自前でSignatureを求める
ついでにSignature Base Stringから自分で求めてみる方法も。
Signatureがどうしても一致しない場合の原因究明をする場合などに、自前でやる方法は把握しておくと役に立つ。
# というかRubyのoauthのドキュメントが整備不足なのでこのあたり自前実装している人が多いような気がする。
require 'openssl'
require 'oauth'
def my_signature(consumer, request)
headers = oauth_headers(request)
signature = OAuth::Signature.build(request) do
[headers['oauth_token_secret'], consumer.secret]
end
digest = OpenSSL::Digest::Digest.new("sha1")
secret = "#{escape(consumer.secret)}&#{escape(headers['oauth_token_secret'])}"
signature_string = Base64.encode64(OpenSSL::HMAC.digest(digest, secret, signature.signature_base_string)).chomp.gsub(/\n/, "")
end
def escape(value)
URI.escape(value.to_s, /[^a-zA-Z0-9\-\.\_\~]/) # Unreserved characters -- must not be encoded
end
# oauth_headersは略
上記コードの自前Signatureを求めるあたりはroauthから拝借した。
Signature Base String求めるとこは手抜きして既存のOAuth::Signatureを使ったもので。
まあSignature Base Stringがおかしい場合は目視でわかるので、自分でSignature計算する前にまずはそこを見てみればいいのかも。