JugemKey認証API Ruby版モジュール
comatta.jpにJugemKey認証APIを導入する為にRuby版モジュールを書きました。PerlとPHPは公式版があるが、Rubyは無いので公開してみます。なお、後述しますが、公式版より機能は少ないです。
使い方は、はてな認証API Ruby版モジュールと殆ど同じです。なお、ソースも殆ど同じです。
はてな認証API Ruby 版モジュール作りました - 2nd life
ただし、はてな認証APIで
hatena_auth = Hatena::API::Auth.new(:api_key => API_KEY, :secret => SECRET)
の部分が
jugem_auth = Jugem::Auth.new(:api_key => API_KEY, :secret => SECRET, :callback_url => CALLBACK_URL, :perms => PERMS)
となります。これはJugemKeyのインターフェイスがはてな認証APIと違うためです。
JugemKey認証APIが想定する利用法は最初にTokenを取得した後、そのTokenを使って個別のAPIにアクセスするようです。ただし、現在利用可能なAPIはユーザ名取得のみなので、loginメソッドで直接ユーザ名を返却しています。従って、Tokenを取得できる公式版より機能が少ないです。
なお、ライセンスはMITライセンスとします。
require 'net/http' require 'openssl' require 'rexml/document' require 'uri' module Jugem class AuthError < RuntimeError;end class Auth API_URI = 'https://secure.jugemkey.jp/' AUTH_URI = 'http://api.jugemkey.jp/api/auth/token' VERSION = '0.0.1' attr_accessor :api_key, :secret, :callback_url, :perms def initialize(options = {}) @api_key = options[:api_key] @secret = options[:secret] @callback_url = options[:callback_url] @perms = options[:perms] end def uri_to_login uri = URI.parse API_URI uri.query = query_with_api_sig uri end def login(frob) time = Time.now.getutc.xmlschema header = { 'X-JUGEMKEY-API-CREATED' => time, 'X-JUGEMKEY-API-KEY' => @api_key, 'X-JUGEMKEY-API-FROB' => frob, 'X-JUGEMKEY-API-SIG' => auth_sig(frob, time), 'User-Agent' => "#{self.class}/#{VERSION} - Ruby" } uri = URI.parse(AUTH_URI) Net::HTTP.start(uri.host) do |http| response = http.get(uri.path, header) unless response.code.to_i == 200 response.body =~ /<error>([^<]*)<\/error>/i raise AuthError.new($1) end doc = REXML::Document.new(response.body) login = doc.elements["entry/title"].text end end private def api_sig OpenSSL::HMAC.hexdigest( OpenSSL::Digest::SHA1.new, @secret, @api_key + @callback_url + @perms) end def auth_sig(frob, time) OpenSSL::HMAC.hexdigest( OpenSSL::Digest::SHA1.new, @secret, @api_key + time + frob) end def query_with_api_sig query = [ [:mode, 'auth_issue_frob'], [:api_key, @api_key], [:perms, @perms], [:callback_url, URI.escape(@callback_url)], [:api_sig, api_sig], ] query.map {|i| i.join '=' }.join('&') end end end