認証APIいろいろをRubyで使う
はてな認証API
Rubyではてな
Hatena::API::AuthのRuby版をid:secondlifeさんが公開してくれてる。
gem install hatenaapiauth
require 'rubygems' require 'hatena/api/auth' require 'cgi' cgi = CGI.new params = { :api_key=>"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", :secret=>"xxxxxxxxxxxxxxxx" } auth = Hatena::API::Auth.new(params) begin hatena = auth.login(cgi['cert']) # hatena = { # "name" => "taslam", # "image_url" => "http://www.hatena.ne.jp/users/ta/taslam/profile.gif", # "thumbnail_url" => "http://www.hatena.ne.jp/users/ta/taslam/profile_s.gif" # } rescue Hatena::API::AuthError => e # 認証失敗 # auth.uri_to_login.to_s にリダイレクトではてなの認証ページに。 end
livedoor Auth
Rubyでlivedoor Auth
gem install livedoorauth
require 'rubygems' require 'livedoorauth' require 'cgi' params = { :app_key=>"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", :secret=>"xxxxxxxxxxxxxxxx" } cgi = CGI.new auth = Livedoor::API::Auth.new(params) begin user = auth.validate_response(cgi.query_string) # user = { # :userhash => 'ユーザを識別するアプリ毎に一意な文字列', # :token => 'LivedoorID取得に用いるtoken', # :userdata => '認証URL生成時に指定した引継ぎデータ', # } # 認証成功 # URL生成時に:perms => 'id'を指定していればLivedoorIDを取得可能。 # livedoor_id = auth.get_livedoor_id(user) rescue # 認証失敗 # ログイン用URIインスタンス取得 # Livedoorへのログイン、アプリケーションの認証情報利用の許可など # 認証できたらあらかじめ設定しているコールバックURLにリダイレクト要求発生 # userdataはそのままコールバックURLに付加されて帰ってくる # :permsのデフォルトはuserhash。idにすると、LivedoorIDを取得できるようになる。 login_uri = auth.uri_to_login(:userdata => 'data') # login_uri にリダイレクトで、Livedoorに認証ページに。 end
YahooBBAuth
http://developer.yahoo.com/auth/
Yahoo!Japanのほうは、現在のところ一般公開はしていない模様(´・ω・`)
GoogleAccountAuthenticationを使う。
http://code.google.com/apis/accounts/AuthForWebApps.html
RubyでGoogleAccountAuthentication
GoogleCalendarサービスでの認証を利用する。
今回はライブラリがあったので、利用させていただいた。
gem install gcalapi
begin GoogleCalendar::Service.new('taslam@example.com', 'password') # カレンダー取得メソッド内で認証してるので利用。 # 直接認証メソッドを叩くなら、srv.instance_eval('auth') srv.calendars rescue GoogleCalendar::AuthenticationFailed => e # 認証失敗 end
Flickr
http://flickr.com/services/api/auth.howto.web.html
RubyでFlickr認証
認証のための、使い易いライブラリが見つからなかったので簡単につくってみた。
flickr/api/auth.rb
require 'digest/md5' require 'uri' require 'open-uri' require 'rexml/document' module Flickr module API class AuthError < RuntimeError;end class Auth def initialize(params) @api_key = params[:api_key].to_s @secret = params[:secret].to_s end def login(frob) return nil if frob.to_s.empty? uri = service_uri('rest') params = { :api_key => @api_key, :method => 'flickr.auth.getToken', :frob => frob.to_s } uri.query = params.merge!(:api_sig => sigunature(params)).collect { |key, value| "#{key}=#{value}"}.join('&') doc = REXML::Document.new(uri.read) rsp = doc.elements['//rsp'] if rsp.attributes['stat'] == 'fail' raise AuthError.new(rsp.elements['err'].attributes['msg']) end auth = doc.elements['//auth'] { :token => auth.elements['token'].text, :perms => auth.elements['perms'].text, :user => { :nsid => auth.elements['user'].attributes['nsid'], :username => auth.elements['user'].attributes['username'], :fullname => auth.elements['user'].attributes['fullname'], } } end def uri_to_login(perm = 'read') uri = service_uri('auth') params = { :api_key => @api_key, :perms => perm } uri.query = params.merge!(:api_sig => sigunature(params)).collect { |key, value| "#{key}=#{value}"}.join('&') uri end private def service_uri(path = 'auth') URI.join('http://flickr.com/services/', path) end def sigunature(params) Digest::MD5.hexdigest(@secret+params.sort_by{|key, value| key.to_s }.flatten.join).to_s end end end end
こんなかんじに使う。
require 'flickr/api/auth' require 'cgi' params = { :api_key=>"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", :secret=>"xxxxxxxxxxxxxxxx" } cgi = CGI.new auth = Flickr::API::Auth.new(params) if info = auth.login(cgi['frob']) # 認証成功 # infoの例 # info => { # :user => { # :nsid=>"000000@N00", # :username=>"taslam", # :fullname=>"" # }, # :token=>"72157603867040929-8ffc565113df0adc", # :perms=>"read" # } else # 認証失敗 # auth.uri_to_login.to_s にリダイレクト要求 end
Jugem
RubyでJugem認証
llameradaさんがライブラリを公開してくれてるのでそれを使わせていただく。
require 'jugem/auth' require 'cgi' params = { :api_key => "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" :secret => "xxxxxxxxxxxxxxxx", :callback_url => "登録したURLを含むコールバック先。この例ではこのCGIのURL。", :perms => "read" } cgi = CGI.new auth = Jugem::Auth.new(params) begin jugem = auth.login(cgi['frob'].to_s) # 認証 rescue Jugem::AuthError => e # 認証失敗 # auth.uri_to_login.to_s にリダイレクト end
OpenID
RubyでOpenID
ruby-openidライブラリを使う。OpenID2.0にも対応しているので、Yahoo!のでも大丈夫。
gem install ruby-openid
immediateを使わない場合のサンプル。普通はこれでいいと思います。
Yahoo!でOpenIDつくってるひとは、identifierは「yahoo.co.jp」だけで良いです。
#!/usr/bin/ruby require 'rubygems' require 'openid' require 'openid/store/filesystem' require 'cgi' require 'cgi/session' require 'cgi/session/pstore' @cgi = CGI.new session = CGI::Session.new(@cgi,'database_manager' => CGI::Session::PStore) def render(text) @cgi.out do text end end def redirect_to(url) print @cgi.header({'status' => '302 Found', 'Location' => url }) end store = OpenID::Store::Filesystem.new('鍵交換データの保存先') consumer = OpenID::Consumer.new(session, store) if session[:verified_identifier] # ログイン済み render "#{session[:verified_identifier]}でログイン済み" else if !@cgi['openid.mode'].empty? #認証結果をコールバックでもらった params = @cgi.params.clone params.each { |k, v| params[k] = v[0] } oid_res = consumer.complete(params, 'コールバックURL(自身のURL)') case oid_res.status when OpenID::Consumer::FAILURE # 認証に失敗した。メッセージがoid_res.messageで取得可能。 render oid_res.message when OpenID::Consumer::SUCCESS session[:verified_identifier] = oid_res.display_identifier redirect_to 'ログイン後のページのURL' when OpenID::Consumer::CANCEL # 認証をユーザがキャンセルした render "キャンセルされました" end elsif !@cgi['openid_identifier'].empty? # フォームにIdentifier(URL)が入力されたので、認証処理を開始する # @cgi['openid_identifier']では以下の警告が出て動かない。 # CAUTION! cgi['key'] == cgi.params['key'][0]; if want Array, use cgi.params['key'] identifier = @cgi.params['openid_identifier'][0] oid_req = consumer.begin(identifier) # コンシューマ識別用URLはプロバイダの認証画面で表示されるURLっぽい。 # 注意としては、コールバックURLはコンシューマ識別用URLが部分一致しなければならないこと。 redirect_to oid_req.redirect_url('コンシューマ識別用URL', 'コールバックURL') else # フォーム表示 render <<-FORM <h1>OpenID サンプル</h1> <form method="post"> <input id="openid_identifier" name="openid_identifier" type="text" value="" /> <input name="commit" type="submit" value="認証" /> </form> FORM end end
mixi
少なくとも一般公開されてる認証APIはいまのところなさげ。やるならMixiStationの足跡APIのハックとなりそう。
まちゅダイアリーで紹介されているように、ユーザーから受け取ったアカウントと、パスワード(のwsse:PasswordDigest)を使ってAPIを叩いて認証に成功するかどうか確認する。
Rubyでmixi認証
//wsse.jsを使わせていただく。 //http://rvr.typepad.com/wind/2005/07/wsse_for_javasc.html function sendWSSE(form, requestURL) { var username = null; var password = null; var elements = form.getElements(); elements.each(function(element, index) { if(element.getAttribute('name') == 'email') username = element.value; if(element.getAttribute('name') == 'password') password = element.value; }); var wsseForm = document.getElementById('wsseForm') || document.createElement('form'); wsseForm.setAttribute('id', 'wsseForm'); wsseForm.action = requestURL; wsseForm.method = 'POST'; var wsseField = document.getElementById('wsseField') || document.createElement('input'); wsseField.setAttribute('id', 'wsseField'); wsseField.name = 'wsse'; wsseField.type = 'hidden'; wsseField.value = wsseHeader(username, password); document.body.appendChild(wsseForm); wsseForm.appendChild(wsseField); wsseForm.submit(); return false; }
<form onsubmit="return sendWSSE(this, 'mixi.cgi');"> mixi<br /> e-mail:<input type="text" name="email" value="" /><br /> password:<input type="password" name="password" value="" /><br /> <input type="submit" value="ログイン" /> </form>
require 'cgi' require 'open-uri' def mixi_login(wsse) open('http://mixi.jp/atom/tracks', 'X-WSSE' => wsse) true rescue OpenURI::HTTPError => e false end @cgi = CGI.new mixi_login(@cgi['wsse']) # => 認証成功したらtrue