| 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