annotate .svn/pristine/47/478eea0d533e8053ee16800d8a6228965a404db6.svn-base @ 1519:afce8026aaeb redmine-2.4-integration

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