Class | Rack::Auth::OpenID |
In: |
lib/rack/auth/openid.rb
|
Parent: | AbstractHandler |
Rack::Auth::OpenID provides a simple method for permitting openid based logins. It requires the ruby-openid lib from janrain to operate, as well as some method of session management of a Hash type.
After a transaction, the response status object is stored in the environment at rack.auth.openid.status, which can be used in the followup block or in a wrapping application to accomplish additional data maniipulation.
NOTE: Due to the amount of data that ruby-openid stores in the session, Rack::Session::Cookie may fault.
A hash of data is stored in the session hash at the key of :openid. The fully canonicalized identity url is stored within at ‘identity’. Extension data from ‘openid.sreg.nickname’ would be stored as { ‘nickname’ => value }.
NOTE: To my knowledge there is no collision at this point from storage of this manner, if there is please let me know so I may adjust this app to cope.
OIDStore | = | ::OpenID::MemoryStore.new | Required for ruby-openid |
A Hash of options is taken as it‘s single initializing argument. String keys are taken to be openid protocol extension namespaces.
For example: 'sreg' => { 'required' => # 'nickname' }
Other keys are taken as options for Rack::Auth::OpenID, normally Symbols. Only :return is required. :trust is highly recommended to be set.
# File lib/rack/auth/openid.rb, line 48 48: def initialize(options={}) 49: raise ArgumentError, 'No return url provided.' unless options[:return] 50: warn 'No trust url provided.' unless options[:trust] 51: options[:trust] ||= options[:return] 52: 53: @options = { 54: :session_key => 'rack.session' 55: }.merge(options) 56: end
# File lib/rack/auth/openid.rb, line 101 101: def auth_fail 102: @options. 103: fetch :auth_fail, [500, {'Content-Type'=>'text/plain'},'Foreign server failure.'] 104: end
# File lib/rack/auth/openid.rb, line 105 105: def bad_login 106: @options. 107: fetch :bad_login, [401, {'Content-Type'=>'text/plain'},'Identification has failed.'] 108: end
# File lib/rack/auth/openid.rb, line 58 58: def call(env) 59: request = Rack::Request.new env 60: return no_session unless session = request.env[@options[:session_key]] 61: resp = if request.GET['openid.mode'] 62: finish session, request.GET, env 63: elsif request.GET['openid_url'] 64: check session, request.GET['openid_url'], env 65: else 66: bad_request 67: end 68: end
# File lib/rack/auth/openid.rb, line 70 70: def check(session, oid_url, env) 71: consumer = ::OpenID::Consumer.new session, OIDStore 72: oid = consumer.begin oid_url 73: return auth_fail unless oid.status == ::OpenID::SUCCESS 74: @options.each do |ns,s| 75: next unless ns.is_a? String 76: s.each {|k,v| oid.add_extension_arg(ns, k, v) } 77: end 78: r_url = @options.fetch :return do |k| request.url end 79: t_url = @options.fetch :trust 80: env['rack.auth.openid.status'] = oid 81: return 303, {'Location'=>oid.redirect_url( t_url, r_url )}, [] 82: end
# File lib/rack/auth/openid.rb, line 84 84: def finish(session, params, env) 85: consumer = ::OpenID::Consumer.new session, OIDStore 86: oid = consumer.complete params 87: return bad_login unless oid.status == ::OpenID::SUCCESS 88: session[:openid] = {'identity' => oid.identity_url} 89: @options.each do |ns,s| 90: next unless ns.is_a? String 91: oid.extension_response(ns).each{|k,v| session[k]=v } 92: end 93: env['rack.auth.openid.status'] = oid 94: return 303, {'Location'=>@options[:trust]}, [] 95: end