To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / .svn / pristine / 47 / 478eea0d533e8053ee16800d8a6228965a404db6.svn-base @ 1298:4f746d8966dd
History | View | Annotate | Download (4.34 KB)
| 1 |
require 'uri' |
|---|---|
| 2 |
require 'openid' |
| 3 |
require 'rack/openid' |
| 4 |
|
| 5 |
module OpenIdAuthentication |
| 6 |
def self.new(app) |
| 7 |
store = OpenIdAuthentication.store |
| 8 |
if store.nil? |
| 9 |
Rails.logger.warn "OpenIdAuthentication.store is nil. Using in-memory store." |
| 10 |
end |
| 11 |
|
| 12 |
::Rack::OpenID.new(app, OpenIdAuthentication.store) |
| 13 |
end |
| 14 |
|
| 15 |
def self.store |
| 16 |
@@store |
| 17 |
end |
| 18 |
|
| 19 |
def self.store=(*store_option) |
| 20 |
store, *parameters = *([ store_option ].flatten) |
| 21 |
|
| 22 |
@@store = case store |
| 23 |
when :memory |
| 24 |
require 'openid/store/memory' |
| 25 |
OpenID::Store::Memory.new |
| 26 |
when :file |
| 27 |
require 'openid/store/filesystem' |
| 28 |
OpenID::Store::Filesystem.new(Rails.root.join('tmp/openids'))
|
| 29 |
when :memcache |
| 30 |
require 'memcache' |
| 31 |
require 'openid/store/memcache' |
| 32 |
OpenID::Store::Memcache.new(MemCache.new(parameters)) |
| 33 |
else |
| 34 |
store |
| 35 |
end |
| 36 |
end |
| 37 |
|
| 38 |
self.store = nil |
| 39 |
|
| 40 |
class InvalidOpenId < StandardError |
| 41 |
end |
| 42 |
|
| 43 |
class Result |
| 44 |
ERROR_MESSAGES = {
|
| 45 |
:missing => "Sorry, the OpenID server couldn't be found", |
| 46 |
:invalid => "Sorry, but this does not appear to be a valid OpenID", |
| 47 |
:canceled => "OpenID verification was canceled", |
| 48 |
:failed => "OpenID verification failed", |
| 49 |
:setup_needed => "OpenID verification needs setup" |
| 50 |
} |
| 51 |
|
| 52 |
def self.[](code) |
| 53 |
new(code) |
| 54 |
end |
| 55 |
|
| 56 |
def initialize(code) |
| 57 |
@code = code |
| 58 |
end |
| 59 |
|
| 60 |
def status |
| 61 |
@code |
| 62 |
end |
| 63 |
|
| 64 |
ERROR_MESSAGES.keys.each { |state| define_method("#{state}?") { @code == state } }
|
| 65 |
|
| 66 |
def successful? |
| 67 |
@code == :successful |
| 68 |
end |
| 69 |
|
| 70 |
def unsuccessful? |
| 71 |
ERROR_MESSAGES.keys.include?(@code) |
| 72 |
end |
| 73 |
|
| 74 |
def message |
| 75 |
ERROR_MESSAGES[@code] |
| 76 |
end |
| 77 |
end |
| 78 |
|
| 79 |
# normalizes an OpenID according to http://openid.net/specs/openid-authentication-2_0.html#normalization |
| 80 |
def self.normalize_identifier(identifier) |
| 81 |
# clean up whitespace |
| 82 |
identifier = identifier.to_s.strip |
| 83 |
|
| 84 |
# if an XRI has a prefix, strip it. |
| 85 |
identifier.gsub!(/xri:\/\//i, '') |
| 86 |
|
| 87 |
# dodge XRIs -- TODO: validate, don't just skip. |
| 88 |
unless ['=', '@', '+', '$', '!', '('].include?(identifier.at(0))
|
| 89 |
# does it begin with http? if not, add it. |
| 90 |
identifier = "http://#{identifier}" unless identifier =~ /^http/i
|
| 91 |
|
| 92 |
# strip any fragments |
| 93 |
identifier.gsub!(/\#(.*)$/, '') |
| 94 |
|
| 95 |
begin |
| 96 |
uri = URI.parse(identifier) |
| 97 |
uri.scheme = uri.scheme.downcase if uri.scheme # URI should do this |
| 98 |
identifier = uri.normalize.to_s |
| 99 |
rescue URI::InvalidURIError |
| 100 |
raise InvalidOpenId.new("#{identifier} is not an OpenID identifier")
|
| 101 |
end |
| 102 |
end |
| 103 |
|
| 104 |
return identifier |
| 105 |
end |
| 106 |
|
| 107 |
protected |
| 108 |
# The parameter name of "openid_identifier" is used rather than |
| 109 |
# the Rails convention "open_id_identifier" because that's what |
| 110 |
# the specification dictates in order to get browser auto-complete |
| 111 |
# working across sites |
| 112 |
def using_open_id?(identifier = nil) #:doc: |
| 113 |
identifier ||= open_id_identifier |
| 114 |
!identifier.blank? || request.env[Rack::OpenID::RESPONSE] |
| 115 |
end |
| 116 |
|
| 117 |
def authenticate_with_open_id(identifier = nil, options = {}, &block) #:doc:
|
| 118 |
identifier ||= open_id_identifier |
| 119 |
|
| 120 |
if request.env[Rack::OpenID::RESPONSE] |
| 121 |
complete_open_id_authentication(&block) |
| 122 |
else |
| 123 |
begin_open_id_authentication(identifier, options, &block) |
| 124 |
end |
| 125 |
end |
| 126 |
|
| 127 |
private |
| 128 |
def open_id_identifier |
| 129 |
params[:openid_identifier] || params[:openid_url] |
| 130 |
end |
| 131 |
|
| 132 |
def begin_open_id_authentication(identifier, options = {})
|
| 133 |
options[:identifier] = identifier |
| 134 |
value = Rack::OpenID.build_header(options) |
| 135 |
response.headers[Rack::OpenID::AUTHENTICATE_HEADER] = value |
| 136 |
head :unauthorized |
| 137 |
end |
| 138 |
|
| 139 |
def complete_open_id_authentication |
| 140 |
response = request.env[Rack::OpenID::RESPONSE] |
| 141 |
identifier = response.display_identifier |
| 142 |
|
| 143 |
case response.status |
| 144 |
when OpenID::Consumer::SUCCESS |
| 145 |
yield Result[:successful], identifier, |
| 146 |
OpenID::SReg::Response.from_success_response(response) |
| 147 |
when :missing |
| 148 |
yield Result[:missing], identifier, nil |
| 149 |
when :invalid |
| 150 |
yield Result[:invalid], identifier, nil |
| 151 |
when OpenID::Consumer::CANCEL |
| 152 |
yield Result[:canceled], identifier, nil |
| 153 |
when OpenID::Consumer::FAILURE |
| 154 |
yield Result[:failed], identifier, nil |
| 155 |
when OpenID::Consumer::SETUP_NEEDED |
| 156 |
yield Result[:setup_needed], response.setup_url, nil |
| 157 |
end |
| 158 |
end |
| 159 |
end |