openid_auth 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG ADDED
@@ -0,0 +1,35 @@
1
+ * Fake HTTP method from OpenID server since they only support a GET. Eliminates the need to set an extra route to match the server's reply. [Josh Peek]
2
+
3
+ * OpenID 2.0 recommends that forms should use the field name "openid_identifier" rather than "openid_url" [Josh Peek]
4
+
5
+ * Return open_id_response.display_identifier to the application instead of .endpoints.claimed_id. [nbibler]
6
+
7
+ * Add Timeout protection [Rick]
8
+
9
+ * An invalid identity url passed through authenticate_with_open_id will no longer raise an InvalidOpenId exception. Instead it will return Result[:missing] to the completion block.
10
+
11
+ * Allow a return_to option to be used instead of the requested url [Josh Peek]
12
+
13
+ * Updated plugin to use Ruby OpenID 2.x.x [Josh Peek]
14
+
15
+ * Tied plugin to ruby-openid 1.1.4 gem until we can make it compatible with 2.x [DHH]
16
+
17
+ * Use URI instead of regexps to normalize the URL and gain free, better matching #8136 [dkubb]
18
+
19
+ * Allow -'s in #normalize_url [Rick]
20
+
21
+ * remove instance of mattr_accessor, it was breaking tests since they don't load ActiveSupport. Fix Timeout test [Rick]
22
+
23
+ * Throw a InvalidOpenId exception instead of just a RuntimeError when the URL can't be normalized [DHH]
24
+
25
+ * Just use the path for the return URL, so extra query parameters don't interfere [DHH]
26
+
27
+ * Added a new default database-backed store after experiencing trouble with the filestore on NFS. The file store is still available as an option [DHH]
28
+
29
+ * Added normalize_url and applied it to all operations going through the plugin [DHH]
30
+
31
+ * Removed open_id? as the idea of using the same input box for both OpenID and username has died -- use using_open_id? instead (which checks for the presence of params[:openid_url] by default) [DHH]
32
+
33
+ * Added OpenIdAuthentication::Result to make it easier to deal with default situations where you don't care to do something particular for each error state [DHH]
34
+
35
+ * Stop relying on root_url being defined, we can just grab the current url instead [DHH]
data/README.markdown ADDED
@@ -0,0 +1,222 @@
1
+ OpenIdAuthentication
2
+ ====================
3
+
4
+ Same as forked version, but modified for SimpleDB.
5
+
6
+ Provides a thin wrapper around the excellent ruby-openid gem from JanRan. Be sure to install that first:
7
+
8
+ gem install ruby-openid
9
+
10
+ To understand what OpenID is about and how it works, it helps to read the documentation for lib/openid/consumer.rb
11
+ from that gem.
12
+
13
+ The specification used is http://openid.net/specs/openid-authentication-2_0.html.
14
+
15
+
16
+ Prerequisites
17
+ =============
18
+
19
+ OpenID authentication uses the session, so be sure that you haven't turned that off. It also relies on a number of
20
+ database tables to store the authentication keys.
21
+
22
+ This particular plugin also relies on the fact that the authentication action allows for both POST and GET operations.
23
+ If you're using RESTful authentication, you'll need to explicitly allow for this in your routes.rb.
24
+
25
+ The plugin also expects to find a root_url method that points to the home page of your site. You can accomplish this by using a root route in config/routes.rb:
26
+
27
+ map.root :controller => 'articles'
28
+
29
+ The root_url will be used as the default return_to and realm value for OpenID. If you'd like to specify a different
30
+ realm, just pass in :realm=>"http://*.mydomain.com" in the options for authenticate_with_open_id.
31
+
32
+ Example
33
+ =======
34
+
35
+ This example is just to meant to demonstrate how you could use OpenID authentication. You might well want to add
36
+ salted hash logins instead of plain text passwords and other requirements on top of this. Treat it as a starting point,
37
+ not a destination.
38
+
39
+ Note that the User model referenced in the simple example below has an 'identity_url' attribute. You will want to add the same or similar field to whatever
40
+ model you are using for authentication.
41
+
42
+ Also of note is the following code block used in the example below:
43
+
44
+ authenticate_with_open_id do |result, identity_url|
45
+ ...
46
+ end
47
+
48
+ In the above code block, 'identity_url' will need to match user.identity_url exactly. 'identity_url' will be a string in the form of 'http://example.com' -
49
+ If you are storing just 'example.com' with your user, the lookup will fail.
50
+
51
+ There is a handy method in this plugin called 'normalize_url' that will help with validating OpenID URLs.
52
+
53
+ OpenIdAuthentication.normalize_url(user.identity_url)
54
+
55
+ The above will return a standardized version of the OpenID URL - the above called with 'example.com' will return 'http://example.com/'
56
+ It will also raise an InvalidOpenId exception if the URL is determined to not be valid.
57
+ Use the above code in your User model and validate OpenID URLs before saving them.
58
+
59
+ config/routes.rb
60
+
61
+ map.root :controller => 'articles'
62
+ map.resource :session
63
+
64
+
65
+ app/views/sessions/new.erb
66
+
67
+ <% form_tag(session_url) do %>
68
+ <p>
69
+ <label for="name">Username:</label>
70
+ <%= text_field_tag "name" %>
71
+ </p>
72
+
73
+ <p>
74
+ <label for="password">Password:</label>
75
+ <%= password_field_tag %>
76
+ </p>
77
+
78
+ <p>
79
+ ...or use:
80
+ </p>
81
+
82
+ <p>
83
+ <label for="openid_identifier">OpenID:</label>
84
+ <%= text_field_tag "openid_identifier" %>
85
+ </p>
86
+
87
+ <p>
88
+ <%= submit_tag 'Sign in', :disable_with => "Signing in&hellip;" %>
89
+ </p>
90
+ <% end %>
91
+
92
+ app/controllers/sessions_controller.rb
93
+ class SessionsController < ApplicationController
94
+ def create
95
+ if using_open_id?
96
+ open_id_authentication
97
+ else
98
+ password_authentication(params[:name], params[:password])
99
+ end
100
+ end
101
+
102
+
103
+ protected
104
+ def password_authentication(name, password)
105
+ if @current_user = @account.users.authenticate(params[:name], params[:password])
106
+ successful_login
107
+ else
108
+ failed_login "Sorry, that username/password doesn't work"
109
+ end
110
+ end
111
+
112
+ def open_id_authentication
113
+ authenticate_with_open_id do |result, identity_url|
114
+ if result.successful?
115
+ if @current_user = @account.users.find_by_identity_url(identity_url)
116
+ successful_login
117
+ else
118
+ failed_login "Sorry, no user by that identity URL exists (#{identity_url})"
119
+ end
120
+ else
121
+ failed_login result.message
122
+ end
123
+ end
124
+ end
125
+
126
+
127
+ private
128
+ def successful_login
129
+ session[:user_id] = @current_user.id
130
+ redirect_to(root_url)
131
+ end
132
+
133
+ def failed_login(message)
134
+ flash[:error] = message
135
+ redirect_to(new_session_url)
136
+ end
137
+ end
138
+
139
+
140
+
141
+ If you're fine with the result messages above and don't need individual logic on a per-failure basis,
142
+ you can collapse the case into a mere boolean:
143
+
144
+ def open_id_authentication
145
+ authenticate_with_open_id do |result, identity_url|
146
+ if result.successful? && @current_user = @account.users.find_by_identity_url(identity_url)
147
+ successful_login
148
+ else
149
+ failed_login(result.message || "Sorry, no user by that identity URL exists (#{identity_url})")
150
+ end
151
+ end
152
+ end
153
+
154
+
155
+ Simple Registration OpenID Extension
156
+ ====================================
157
+
158
+ Some OpenID Providers support this lightweight profile exchange protocol. See more: http://www.openidenabled.com/openid/simple-registration-extension
159
+
160
+ You can support it in your app by changing #open_id_authentication
161
+
162
+ def open_id_authentication(identity_url)
163
+ # Pass optional :required and :optional keys to specify what sreg fields you want.
164
+ # Be sure to yield registration, a third argument in the #authenticate_with_open_id block.
165
+ authenticate_with_open_id(identity_url,
166
+ :required => [ :nickname, :email ],
167
+ :optional => :fullname) do |result, identity_url, registration|
168
+ case result.status
169
+ when :missing
170
+ failed_login "Sorry, the OpenID server couldn't be found"
171
+ when :invalid
172
+ failed_login "Sorry, but this does not appear to be a valid OpenID"
173
+ when :canceled
174
+ failed_login "OpenID verification was canceled"
175
+ when :failed
176
+ failed_login "Sorry, the OpenID verification failed"
177
+ when :successful
178
+ if @current_user = @account.users.find_by_identity_url(identity_url)
179
+ assign_registration_attributes!(registration)
180
+
181
+ if current_user.save
182
+ successful_login
183
+ else
184
+ failed_login "Your OpenID profile registration failed: " +
185
+ @current_user.errors.full_messages.to_sentence
186
+ end
187
+ else
188
+ failed_login "Sorry, no user by that identity URL exists"
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ # registration is a hash containing the valid sreg keys given above
195
+ # use this to map them to fields of your user model
196
+ def assign_registration_attributes!(registration)
197
+ model_to_registration_mapping.each do |model_attribute, registration_attribute|
198
+ unless registration[registration_attribute].blank?
199
+ @current_user.send("#{model_attribute}=", registration[registration_attribute])
200
+ end
201
+ end
202
+ end
203
+
204
+ def model_to_registration_mapping
205
+ { :login => 'nickname', :email => 'email', :display_name => 'fullname' }
206
+ end
207
+
208
+ Attribute Exchange OpenID Extension
209
+ ===================================
210
+
211
+ Some OpenID providers also support the OpenID AX (attribute exchange) protocol for exchanging identity information between endpoints. See more: http://openid.net/specs/openid-attribute-exchange-1_0.html
212
+
213
+ Accessing AX data is very similar to the Simple Registration process, described above -- just add the URI identifier for the AX field to your :optional or :required parameters. For example:
214
+
215
+ authenticate_with_open_id(identity_url,
216
+ :required => [ :email, 'http://schema.openid.net/birthDate' ]) do |result, identity_url, registration|
217
+
218
+ This would provide the sreg data for :email, and the AX data for 'http://schema.openid.net/birthDate'
219
+
220
+
221
+
222
+ Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license
@@ -0,0 +1,17 @@
1
+ require 'base64'
2
+ module OpenIdAuthentication
3
+ class Association < SimpleRecord::Base
4
+
5
+ set_table_name :open_id_authentication_associations
6
+
7
+ has_attributes :handle,
8
+ :secret,
9
+ :assoc_type, :server_url
10
+
11
+ has_ints :issued, :lifetime
12
+
13
+ def from_record
14
+ OpenID::Association.new(handle, Base64.decode64(secret), issued, lifetime, assoc_type)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,63 @@
1
+ require 'openid/store/interface'
2
+ require 'base64'
3
+
4
+ module OpenIdAuthentication
5
+ class DbStore < OpenID::Store::Interface
6
+ def self.cleanup_nonces
7
+ puts 'deleting nonces'
8
+ now = Time.now.to_i
9
+ Nonce.delete_all(["timestamp > ? OR timestamp < ?", now + OpenID::Nonce.skew, now - OpenID::Nonce.skew])
10
+ puts 'done'
11
+ end
12
+
13
+ def self.cleanup_associations
14
+ now = Time.now.to_i
15
+ Association.delete_all(:all, :conditions => ['issued + lifetime > ?', now])
16
+ end
17
+
18
+ def store_association(server_url, assoc)
19
+ remove_association(server_url, assoc.handle)
20
+ Association.create(:server_url => server_url,
21
+ :handle => assoc.handle,
22
+ :secret => Base64.encode64(assoc.secret),
23
+ :issued => Time.now.to_i, # assoc.issued,
24
+ :lifetime => assoc.lifetime,
25
+ :assoc_type => assoc.assoc_type)
26
+ end
27
+
28
+ def get_association(server_url, handle = nil)
29
+ assocs = if handle.blank?
30
+ Association.find_all_by_server_url(server_url)
31
+ else
32
+ Association.find_all_by_server_url_and_handle(server_url, handle)
33
+ end
34
+
35
+ assocs.each do |assoc|
36
+ a = assoc.from_record
37
+ if a.expires_in.to_i == 0
38
+ assoc.destroy
39
+ else
40
+ return a
41
+ end
42
+ end if assocs.any?
43
+
44
+ return nil
45
+ end
46
+
47
+ def remove_association(server_url, handle)
48
+
49
+ as = Association.find(:all, :conditions => ['server_url = ? AND handle = ?', server_url, handle])
50
+ as.each do |a|
51
+ a.delete
52
+ end
53
+ return as.size > 0
54
+ end
55
+
56
+ def use_nonce(server_url, timestamp, salt)
57
+ return false if Nonce.find_by_server_url_and_timestamp_and_salt(server_url, timestamp, salt)
58
+ return false if (timestamp - Time.now.to_i).abs > OpenID::Nonce.skew
59
+ Nonce.create(:server_url => server_url, :timestamp => timestamp, :salt => salt)
60
+ return true
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,9 @@
1
+ module OpenIdAuthentication
2
+ class Nonce < SimpleRecord::Base
3
+ set_table_name :open_id_authentication_nonces
4
+
5
+ has_attributes :timestamp,
6
+ :salt,
7
+ :server_url
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ module OpenIdAuthentication
2
+ module Request
3
+ def self.included(base)
4
+ base.alias_method_chain :request_method, :openid
5
+ end
6
+
7
+ def request_method_with_openid
8
+ if !parameters[:_method].blank? && parameters[:open_id_complete] == '1'
9
+ parameters[:_method].to_sym
10
+ else
11
+ request_method_without_openid
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ # In Rails 2.3, the request object has been renamed
18
+ # from AbstractRequest to Request
19
+ if defined? ActionController::Request
20
+ ActionController::Request.send :include, OpenIdAuthentication::Request
21
+ else
22
+ ActionController::AbstractRequest.send :include, OpenIdAuthentication::Request
23
+ end
@@ -0,0 +1,20 @@
1
+ # http://trac.openidenabled.com/trac/ticket/156
2
+ module OpenID
3
+ @@timeout_threshold = 20
4
+
5
+ def self.timeout_threshold
6
+ @@timeout_threshold
7
+ end
8
+
9
+ def self.timeout_threshold=(value)
10
+ @@timeout_threshold = value
11
+ end
12
+
13
+ class StandardFetcher
14
+ def make_http(uri)
15
+ http = @proxy.new(uri.host, uri.port)
16
+ http.read_timeout = http.open_timeout = OpenID.timeout_threshold
17
+ http
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,242 @@
1
+ require 'uri'
2
+ require 'openid/extensions/sreg'
3
+ require 'openid/extensions/ax'
4
+ require 'openid/store/filesystem'
5
+
6
+ require File.dirname(__FILE__) + '/open_id_authentication/association'
7
+ require File.dirname(__FILE__) + '/open_id_authentication/nonce'
8
+ require File.dirname(__FILE__) + '/open_id_authentication/db_store'
9
+ require File.dirname(__FILE__) + '/open_id_authentication/request'
10
+ require File.dirname(__FILE__) + '/open_id_authentication/timeout_fixes' if OpenID::VERSION == "2.0.4"
11
+
12
+ module OpenIdAuthentication
13
+ OPEN_ID_AUTHENTICATION_DIR = RAILS_ROOT + "/tmp/openids"
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 :db
24
+ OpenIdAuthentication::DbStore.new
25
+ when :file
26
+ OpenID::Store::Filesystem.new(OPEN_ID_AUTHENTICATION_DIR)
27
+ else
28
+ store
29
+ end
30
+ end
31
+
32
+ self.store = :db
33
+
34
+ class InvalidOpenId < StandardError
35
+ end
36
+
37
+ class Result
38
+ ERROR_MESSAGES = {
39
+ :missing => "Sorry, the OpenID server couldn't be found",
40
+ :invalid => "Sorry, but this does not appear to be a valid OpenID",
41
+ :canceled => "OpenID verification was canceled",
42
+ :failed => "OpenID verification failed",
43
+ :setup_needed => "OpenID verification needs setup"
44
+ }
45
+
46
+ def self.[](code)
47
+ new(code)
48
+ end
49
+
50
+ def initialize(code)
51
+ @code = code
52
+ end
53
+
54
+ def status
55
+ @code
56
+ end
57
+
58
+ ERROR_MESSAGES.keys.each { |state| define_method("#{state}?") { @code == state } }
59
+
60
+ def successful?
61
+ @code == :successful
62
+ end
63
+
64
+ def unsuccessful?
65
+ ERROR_MESSAGES.keys.include?(@code)
66
+ end
67
+
68
+ def message
69
+ ERROR_MESSAGES[@code]
70
+ end
71
+ end
72
+
73
+ # normalizes an OpenID according to http://openid.net/specs/openid-authentication-2_0.html#normalization
74
+ def self.normalize_identifier(identifier)
75
+ # clean up whitespace
76
+ identifier = identifier.to_s.strip
77
+
78
+ # if an XRI has a prefix, strip it.
79
+ identifier.gsub!(/xri:\/\//i, '')
80
+
81
+ # dodge XRIs -- TODO: validate, don't just skip.
82
+ unless ['=', '@', '+', '$', '!', '('].include?(identifier.at(0))
83
+ # does it begin with http? if not, add it.
84
+ identifier = "http://#{identifier}" unless identifier =~ /^http/i
85
+
86
+ # strip any fragments
87
+ identifier.gsub!(/\#(.*)$/, '')
88
+
89
+ begin
90
+ uri = URI.parse(identifier)
91
+ uri.scheme = uri.scheme.downcase # URI should do this
92
+ identifier = uri.normalize.to_s
93
+ rescue URI::InvalidURIError
94
+ raise InvalidOpenId.new("#{identifier} is not an OpenID identifier")
95
+ end
96
+ end
97
+
98
+ return identifier
99
+ end
100
+
101
+ # deprecated for OpenID 2.0, where not all OpenIDs are URLs
102
+ def self.normalize_url(url)
103
+ ActiveSupport::Deprecation.warn "normalize_url has been deprecated, use normalize_identifier instead"
104
+ self.normalize_identifier(url)
105
+ end
106
+
107
+ protected
108
+ def normalize_url(url)
109
+ OpenIdAuthentication.normalize_url(url)
110
+ end
111
+
112
+ def normalize_identifier(url)
113
+ OpenIdAuthentication.normalize_identifier(url)
114
+ end
115
+
116
+ # The parameter name of "openid_identifier" is used rather than the Rails convention "open_id_identifier"
117
+ # because that's what the specification dictates in order to get browser auto-complete working across sites
118
+ def using_open_id?(identity_url = nil) #:doc:
119
+ identity_url ||= params[:openid_identifier] || params[:openid_url]
120
+ !identity_url.blank? || params[:open_id_complete]
121
+ end
122
+
123
+ def authenticate_with_open_id(identity_url = nil, options = {}, &block) #:doc:
124
+ identity_url ||= params[:openid_identifier] || params[:openid_url]
125
+
126
+ if params[:open_id_complete].nil?
127
+ begin_open_id_authentication(identity_url, options, &block)
128
+ else
129
+ complete_open_id_authentication(&block)
130
+ end
131
+ end
132
+
133
+ private
134
+ def begin_open_id_authentication(identity_url, options = {})
135
+ identity_url = normalize_identifier(identity_url)
136
+ return_to = options.delete(:return_to)
137
+ method = options.delete(:method)
138
+
139
+ options[:required] ||= [] # reduces validation later
140
+ options[:optional] ||= []
141
+
142
+ open_id_request = open_id_consumer.begin(identity_url)
143
+ add_simple_registration_fields(open_id_request, options)
144
+ add_ax_fields(open_id_request, options)
145
+ # puts 'OPENID url=' + open_id_redirect_url(open_id_request, return_to, method)
146
+ redirect_to(open_id_redirect_url(open_id_request, return_to, method, options))
147
+ rescue OpenIdAuthentication::InvalidOpenId => e
148
+ yield Result[:invalid], identity_url, nil
149
+ rescue OpenID::OpenIDError, Timeout::Error => e
150
+ logger.error("[OPENID] #{e}")
151
+ yield Result[:missing], identity_url, nil
152
+ end
153
+
154
+
155
+ def complete_open_id_authentication
156
+ params_with_path = params.reject { |key, value| request.path_parameters[key] }
157
+ params_with_path.delete(:format)
158
+ open_id_response = timeout_protection_from_identity_server { open_id_consumer.complete(params_with_path, requested_url) }
159
+ identity_url = normalize_identifier(open_id_response.display_identifier) if open_id_response.display_identifier
160
+
161
+ case open_id_response.status
162
+ when OpenID::Consumer::SUCCESS
163
+ profile_data = {}
164
+
165
+ # merge the SReg data and the AX data into a single hash of profile data
166
+ [ OpenID::SReg::Response, OpenID::AX::FetchResponse ].each do |data_response|
167
+ if data_response.from_success_response( open_id_response )
168
+ profile_data.merge! data_response.from_success_response( open_id_response ).data
169
+ end
170
+ end
171
+
172
+ yield Result[:successful], identity_url, profile_data
173
+ when OpenID::Consumer::CANCEL
174
+ yield Result[:canceled], identity_url, nil
175
+ when OpenID::Consumer::FAILURE
176
+ yield Result[:failed], identity_url, nil
177
+ when OpenID::Consumer::SETUP_NEEDED
178
+ yield Result[:setup_needed], open_id_response.setup_url, nil
179
+ end
180
+ end
181
+
182
+ def open_id_consumer
183
+ OpenID::Consumer.new(session, OpenIdAuthentication.store)
184
+ end
185
+
186
+ def add_simple_registration_fields(open_id_request, fields)
187
+ sreg_request = OpenID::SReg::Request.new
188
+
189
+ # filter out AX identifiers (URIs)
190
+ required_fields = fields[:required].collect { |f| f.to_s unless f =~ /^https?:\/\// }.compact
191
+ optional_fields = fields[:optional].collect { |f| f.to_s unless f =~ /^https?:\/\// }.compact
192
+
193
+ sreg_request.request_fields(required_fields, true) unless required_fields.blank?
194
+ sreg_request.request_fields(optional_fields, false) unless optional_fields.blank?
195
+ sreg_request.policy_url = fields[:policy_url] if fields[:policy_url]
196
+ open_id_request.add_extension(sreg_request)
197
+ end
198
+
199
+ def add_ax_fields( open_id_request, fields )
200
+ ax_request = OpenID::AX::FetchRequest.new
201
+
202
+ # look through the :required and :optional fields for URIs (AX identifiers)
203
+ fields[:required].each do |f|
204
+ next unless f =~ /^https?:\/\//
205
+ ax_request.add( OpenID::AX::AttrInfo.new( f, nil, true ) )
206
+ end
207
+
208
+ fields[:optional].each do |f|
209
+ next unless f =~ /^https?:\/\//
210
+ ax_request.add( OpenID::AX::AttrInfo.new( f, nil, false ) )
211
+ end
212
+
213
+ open_id_request.add_extension( ax_request )
214
+ end
215
+
216
+ def open_id_redirect_url(open_id_request, return_to = nil, method = nil, options={})
217
+ open_id_request.return_to_args['_method'] = (method || request.method).to_s
218
+ open_id_request.return_to_args['open_id_complete'] = '1'
219
+ open_id_request.redirect_url(options[:realm] || root_url, return_to || requested_url)
220
+ end
221
+
222
+ def requested_url
223
+ relative_url_root = self.class.respond_to?(:relative_url_root) ?
224
+ self.class.relative_url_root.to_s :
225
+ request.relative_url_root
226
+ "#{request.protocol}#{request.host_with_port}#{ActionController::Base.relative_url_root}#{request.path}"
227
+ end
228
+
229
+ def timeout_protection_from_identity_server
230
+ yield
231
+ rescue Timeout::Error
232
+ Class.new do
233
+ def status
234
+ OpenID::FAILURE
235
+ end
236
+
237
+ def msg
238
+ "Identity server timed out"
239
+ end
240
+ end.new
241
+ end
242
+ end
@@ -0,0 +1,32 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class NormalizeTest < Test::Unit::TestCase
4
+ include OpenIdAuthentication
5
+
6
+ NORMALIZATIONS = {
7
+ "openid.aol.com/nextangler" => "http://openid.aol.com/nextangler",
8
+ "http://openid.aol.com/nextangler" => "http://openid.aol.com/nextangler",
9
+ "https://openid.aol.com/nextangler" => "https://openid.aol.com/nextangler",
10
+ "HTTP://OPENID.AOL.COM/NEXTANGLER" => "http://openid.aol.com/NEXTANGLER",
11
+ "HTTPS://OPENID.AOL.COM/NEXTANGLER" => "https://openid.aol.com/NEXTANGLER",
12
+ "loudthinking.com" => "http://loudthinking.com/",
13
+ "http://loudthinking.com" => "http://loudthinking.com/",
14
+ "http://loudthinking.com:80" => "http://loudthinking.com/",
15
+ "https://loudthinking.com:443" => "https://loudthinking.com/",
16
+ "http://loudthinking.com:8080" => "http://loudthinking.com:8080/",
17
+ "techno-weenie.net" => "http://techno-weenie.net/",
18
+ "http://techno-weenie.net" => "http://techno-weenie.net/",
19
+ "http://techno-weenie.net " => "http://techno-weenie.net/",
20
+ "=name" => "=name"
21
+ }
22
+
23
+ def test_normalizations
24
+ NORMALIZATIONS.each do |from, to|
25
+ assert_equal to, normalize_identifier(from)
26
+ end
27
+ end
28
+
29
+ def test_broken_open_id
30
+ assert_raises(InvalidOpenId) { normalize_identifier(nil) }
31
+ end
32
+ end
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class OpenIdAuthenticationTest < Test::Unit::TestCase
4
+ def setup
5
+ @controller = Class.new do
6
+ include OpenIdAuthentication
7
+ def params() {} end
8
+ end.new
9
+ end
10
+
11
+ def test_authentication_should_fail_when_the_identity_server_is_missing
12
+ open_id_consumer = mock()
13
+ open_id_consumer.expects(:begin).raises(OpenID::OpenIDError)
14
+ @controller.expects(:open_id_consumer).returns(open_id_consumer)
15
+ @controller.expects(:logger).returns(mock(:error => true))
16
+
17
+ @controller.send(:authenticate_with_open_id, "http://someone.example.com") do |result, identity_url|
18
+ assert result.missing?
19
+ assert_equal "Sorry, the OpenID server couldn't be found", result.message
20
+ end
21
+ end
22
+
23
+ def test_authentication_should_be_invalid_when_the_identity_url_is_invalid
24
+ @controller.send(:authenticate_with_open_id, "!") do |result, identity_url|
25
+ assert result.invalid?, "Result expected to be invalid but was not"
26
+ assert_equal "Sorry, but this does not appear to be a valid OpenID", result.message
27
+ end
28
+ end
29
+
30
+ def test_authentication_should_fail_when_the_identity_server_times_out
31
+ open_id_consumer = mock()
32
+ open_id_consumer.expects(:begin).raises(Timeout::Error, "Identity Server took too long.")
33
+ @controller.expects(:open_id_consumer).returns(open_id_consumer)
34
+ @controller.expects(:logger).returns(mock(:error => true))
35
+
36
+ @controller.send(:authenticate_with_open_id, "http://someone.example.com") do |result, identity_url|
37
+ assert result.missing?
38
+ assert_equal "Sorry, the OpenID server couldn't be found", result.message
39
+ end
40
+ end
41
+
42
+ def test_authentication_should_begin_when_the_identity_server_is_present
43
+ @controller.expects(:begin_open_id_authentication)
44
+ @controller.send(:authenticate_with_open_id, "http://someone.example.com")
45
+ end
46
+ end
@@ -0,0 +1,14 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class StatusTest < Test::Unit::TestCase
4
+ include OpenIdAuthentication
5
+
6
+ def test_state_conditional
7
+ assert Result[:missing].missing?
8
+ assert Result[:missing].unsuccessful?
9
+ assert !Result[:missing].successful?
10
+
11
+ assert Result[:successful].successful?
12
+ assert !Result[:successful].unsuccessful?
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+
4
+ gem 'activesupport'
5
+ require 'active_support'
6
+
7
+ gem 'actionpack'
8
+ require 'action_controller'
9
+
10
+ gem 'mocha'
11
+ require 'mocha'
12
+
13
+ gem 'ruby-openid'
14
+ require 'openid'
15
+
16
+ RAILS_ROOT = File.dirname(__FILE__) unless defined? RAILS_ROOT
17
+ require File.dirname(__FILE__) + "/../lib/open_id_authentication"
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: openid_auth
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Travis Reeder
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-02 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ruby-openid
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: Simple way to add openid to rails apps.
26
+ email: travis@appoxy.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - CHANGELOG
33
+ - README.markdown
34
+ files:
35
+ - lib/open_id_authentication.rb
36
+ - lib/open_id_authentication/association.rb
37
+ - lib/open_id_authentication/db_store.rb
38
+ - lib/open_id_authentication/nonce.rb
39
+ - lib/open_id_authentication/request.rb
40
+ - lib/open_id_authentication/timeout_fixes.rb
41
+ - CHANGELOG
42
+ - README.markdown
43
+ has_rdoc: true
44
+ homepage: http://github.com/appoxy/open_id_authentication
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --charset=UTF-8
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 1.3.5
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Simple way to add openid to rails apps.
71
+ test_files:
72
+ - test/normalize_test.rb
73
+ - test/open_id_authentication_test.rb
74
+ - test/status_test.rb
75
+ - test/test_helper.rb