devise_openid_authenticatable 1.0.0.alpha7 → 1.0.0.beta2
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.rdoc +9 -0
- data/Gemfile +2 -2
- data/README.md +3 -5
- data/VERSION +1 -1
- data/devise_openid_authenticatable.gemspec +6 -2
- data/lib/devise_openid_authenticatable/strategy.rb +47 -18
- data/spec/scenario/app/models/database_user.rb +15 -0
- data/spec/scenario/app/models/legacy_user.rb +18 -0
- data/spec/scenario/app/models/user.rb +2 -2
- data/spec/scenario/config/routes.rb +2 -0
- data/spec/scenario/db/migrate/20100401102949_create_tables.rb +15 -0
- data/spec/strategy_spec.rb +130 -0
- metadata +8 -4
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 1.0.0.beta1
|
2
|
+
* Implement support for build_from_identity_url. create_from_identity_url is now deprecated.
|
3
|
+
* build_from_identity_url should return a new, unsaved model instance rather than a persisted one.
|
4
|
+
* This has multiple benefits: validation should become easier, and we can avoid doing multiple modification queries during the initial registration.
|
5
|
+
* Switching over should be straightforward but is not a simple matter of changing the method's name. Its behavior needs to be altered to return an unsaved instance.
|
6
|
+
* This affects all users of devise_openid_authenticatable.
|
7
|
+
* Attempt to pass a more correct trust_root to the OpenID provider.
|
8
|
+
* Fill out Dimitrij's test suite a bit more.
|
9
|
+
|
1
10
|
== 1.0.0.alpha7
|
2
11
|
|
3
12
|
* GH-3: Add support for rememberable.
|
data/Gemfile
CHANGED
@@ -2,8 +2,8 @@ source "http://rubygems.org"
|
|
2
2
|
|
3
3
|
gem 'rails', '3.0.0'
|
4
4
|
gem "devise", ">= 1.1.2"
|
5
|
-
gem "rspec", "
|
6
|
-
gem "rspec-rails", "
|
5
|
+
gem "rspec", "~> 2.3"
|
6
|
+
gem "rspec-rails", "~> 2.3"
|
7
7
|
gem "rack-openid", ">= 1.2.0"
|
8
8
|
gem "mocha"
|
9
9
|
gem "sqlite3-ruby"
|
data/README.md
CHANGED
@@ -77,14 +77,14 @@ Automatically creating users
|
|
77
77
|
----------------------------
|
78
78
|
|
79
79
|
If you want to have users automatically created when a new OpenID identity URL is
|
80
|
-
successfully used to sign in, you can implement a method called "
|
80
|
+
successfully used to sign in, you can implement a method called "build_from_identity_url"
|
81
81
|
to your user model class:
|
82
82
|
|
83
83
|
class User < ActiveRecord::Base
|
84
84
|
devise :openid_authenticatable
|
85
85
|
|
86
|
-
def self.
|
87
|
-
User.
|
86
|
+
def self.build_from_identity_url(identity_url)
|
87
|
+
User.new(:identity_url => identity_url)
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
@@ -155,6 +155,4 @@ See also
|
|
155
155
|
TODO
|
156
156
|
----
|
157
157
|
|
158
|
-
* Add sreg attributes support
|
159
|
-
* Write test suite
|
160
158
|
* Test on non-ActiveRecord ORMs
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.0.
|
1
|
+
1.0.0.beta2
|
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{devise_openid_authenticatable}
|
8
|
-
s.version = "1.0.0.
|
8
|
+
s.version = "1.0.0.beta2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Nat Budin"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-12-21}
|
13
13
|
s.description = %q{OpenID authentication module for Devise using Rack::OpenID}
|
14
14
|
s.email = %q{natbudin@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -33,6 +33,8 @@ Gem::Specification.new do |s|
|
|
33
33
|
"spec/scenario/app/controllers/application_controller.rb",
|
34
34
|
"spec/scenario/app/controllers/home_controller.rb",
|
35
35
|
"spec/scenario/app/controllers/sessions_controller.rb",
|
36
|
+
"spec/scenario/app/models/database_user.rb",
|
37
|
+
"spec/scenario/app/models/legacy_user.rb",
|
36
38
|
"spec/scenario/app/models/user.rb",
|
37
39
|
"spec/scenario/app/views/layouts/application.html.erb",
|
38
40
|
"spec/scenario/app/views/sessions/new.html.erb",
|
@@ -63,6 +65,8 @@ Gem::Specification.new do |s|
|
|
63
65
|
"spec/scenario/app/controllers/application_controller.rb",
|
64
66
|
"spec/scenario/app/controllers/home_controller.rb",
|
65
67
|
"spec/scenario/app/controllers/sessions_controller.rb",
|
68
|
+
"spec/scenario/app/models/database_user.rb",
|
69
|
+
"spec/scenario/app/models/legacy_user.rb",
|
66
70
|
"spec/scenario/app/models/user.rb",
|
67
71
|
"spec/scenario/config/application.rb",
|
68
72
|
"spec/scenario/config/boot.rb",
|
@@ -19,7 +19,7 @@ class Devise::Strategies::OpenidAuthenticatable < base_class
|
|
19
19
|
if provider_response
|
20
20
|
handle_response!
|
21
21
|
else # Delegate authentication to Rack::OpenID by throwing a 401
|
22
|
-
opts = { :identifier => params[scope]["identity_url"], :return_to => return_url, :method => 'post' }
|
22
|
+
opts = { :identifier => params[scope]["identity_url"], :return_to => return_url, :trust_root => trust_root, :method => 'post' }
|
23
23
|
opts[:optional] = mapping.to.openid_optional_fields if mapping.to.respond_to?(:openid_optional_fields)
|
24
24
|
opts[:required] = mapping.to.openid_required_fields if mapping.to.respond_to?(:openid_required_fields)
|
25
25
|
custom! [401, { Rack::OpenID::AUTHENTICATE_HEADER => Rack::OpenID.build_header(opts) }, "Sign in with OpenID"]
|
@@ -34,14 +34,16 @@ class Devise::Strategies::OpenidAuthenticatable < base_class
|
|
34
34
|
|
35
35
|
case provider_response.status
|
36
36
|
when :success
|
37
|
-
resource =
|
38
|
-
|
39
|
-
resource = mapping.to.create_from_identity_url(provider_response.identity_url)
|
40
|
-
end
|
41
|
-
|
37
|
+
resource = find_resource || build_resource || create_resource
|
38
|
+
|
42
39
|
if resource
|
43
|
-
|
44
|
-
|
40
|
+
begin
|
41
|
+
update_resource!(resource)
|
42
|
+
rescue
|
43
|
+
fail! $!
|
44
|
+
else
|
45
|
+
success!(resource)
|
46
|
+
end
|
45
47
|
else
|
46
48
|
fail! "This OpenID URL is not associated with any registered user"
|
47
49
|
end
|
@@ -70,26 +72,47 @@ class Devise::Strategies::OpenidAuthenticatable < base_class
|
|
70
72
|
def identity_param?
|
71
73
|
params[scope].try(:[], 'identity_url').present?
|
72
74
|
end
|
75
|
+
|
76
|
+
def find_resource
|
77
|
+
mapping.to.find_by_identity_url(provider_response.identity_url)
|
78
|
+
end
|
79
|
+
|
80
|
+
def build_resource
|
81
|
+
if mapping.to.respond_to?(:build_from_identity_url)
|
82
|
+
mapping.to.build_from_identity_url(provider_response.identity_url)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_resource
|
87
|
+
if mapping.to.respond_to?(:create_from_identity_url)
|
88
|
+
logger.warn "DEPRECATION WARNING: create_from_identity_url is deprecated. Please implement build_from_identity_url instead. For more information, please see the devise_openid_authenticatable CHANGELOG for version 1.0.0.beta1."
|
89
|
+
mapping.to.create_from_identity_url(provider_response.identity_url)
|
90
|
+
end
|
91
|
+
end
|
73
92
|
|
74
93
|
def update_resource!(resource)
|
75
|
-
|
76
|
-
|
77
|
-
|
94
|
+
if fields && resource.respond_to?(:openid_fields=)
|
95
|
+
resource.openid_fields = fields
|
96
|
+
end
|
97
|
+
|
98
|
+
resource.save!
|
99
|
+
end
|
100
|
+
|
101
|
+
def fields
|
102
|
+
return @fields unless @fields.nil?
|
103
|
+
|
78
104
|
if axr = OpenID::AX::FetchResponse.from_success_response(provider_response)
|
79
|
-
fields = axr.data
|
105
|
+
@fields = axr.data
|
80
106
|
else
|
81
107
|
provider_response.message.namespaces.each do |uri, ns_alias|
|
82
108
|
if ns_alias.to_s == "sreg"
|
83
|
-
fields = provider_response.extension_response(uri, true)
|
109
|
+
@fields = provider_response.extension_response(uri, true)
|
84
110
|
break
|
85
111
|
end
|
86
112
|
end
|
87
113
|
end
|
88
|
-
|
89
|
-
|
90
|
-
resource.openid_fields = fields
|
91
|
-
resource.save
|
92
|
-
end
|
114
|
+
|
115
|
+
return @fields
|
93
116
|
end
|
94
117
|
|
95
118
|
def logger
|
@@ -107,6 +130,12 @@ class Devise::Strategies::OpenidAuthenticatable < base_class
|
|
107
130
|
return_to.to_s
|
108
131
|
end
|
109
132
|
|
133
|
+
def trust_root
|
134
|
+
trust_root = URI.parse(request.url)
|
135
|
+
trust_root.path = ""
|
136
|
+
trust_root.query = nil
|
137
|
+
trust_root.to_s
|
138
|
+
end
|
110
139
|
end
|
111
140
|
|
112
141
|
Warden::Strategies.add :openid_authenticatable, Devise::Strategies::OpenidAuthenticatable
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class DatabaseUser < ActiveRecord::Base
|
2
|
+
devise :database_authenticatable, :openid_authenticatable, :validatable
|
3
|
+
|
4
|
+
def self.build_from_identity_url(identity_url)
|
5
|
+
new(:identity_url => identity_url)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.openid_required_fields
|
9
|
+
["http://axschema.org/contact/email"]
|
10
|
+
end
|
11
|
+
|
12
|
+
def openid_fields=(fields)
|
13
|
+
self.email = fields["http://axschema.org/contact/email"].first
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class LegacyUser < ActiveRecord::Base
|
2
|
+
devise :openid_authenticatable, :rememberable
|
3
|
+
|
4
|
+
def self.create_from_identity_url(identity_url)
|
5
|
+
create do |user|
|
6
|
+
user.identity_url = identity_url
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.openid_required_fields
|
11
|
+
["http://axschema.org/contact/email"]
|
12
|
+
end
|
13
|
+
|
14
|
+
def openid_fields=(fields)
|
15
|
+
self.email = fields["http://axschema.org/contact/email"].first
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
class User < ActiveRecord::Base
|
2
2
|
devise :openid_authenticatable, :rememberable
|
3
3
|
|
4
|
-
def self.
|
5
|
-
|
4
|
+
def self.build_from_identity_url(identity_url)
|
5
|
+
new do |user|
|
6
6
|
user.identity_url = identity_url
|
7
7
|
end
|
8
8
|
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
2
|
devise_for :users, :controllers => { :sessions => 'sessions' }
|
3
|
+
devise_for :database_users, :controllers => { :sessions => 'sessions' }
|
4
|
+
devise_for :legacy_users, :controllers => { :sessions => 'sessions' }
|
3
5
|
root :to => "home#index"
|
4
6
|
end
|
@@ -6,9 +6,24 @@ class CreateTables < ActiveRecord::Migration
|
|
6
6
|
t.string :email
|
7
7
|
t.timestamps
|
8
8
|
end
|
9
|
+
|
10
|
+
create_table :database_users do |t|
|
11
|
+
t.openid_authenticatable
|
12
|
+
t.database_authenticatable
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table :legacy_users do |t|
|
17
|
+
t.openid_authenticatable
|
18
|
+
t.rememberable
|
19
|
+
t.string :email
|
20
|
+
t.timestamps
|
21
|
+
end
|
9
22
|
end
|
10
23
|
|
11
24
|
def self.down
|
12
25
|
drop_table :users
|
26
|
+
drop_table :database_users
|
27
|
+
drop_table :legacy_users
|
13
28
|
end
|
14
29
|
end
|
data/spec/strategy_spec.rb
CHANGED
@@ -39,10 +39,22 @@ describe Devise::Strategies::OpenidAuthenticatable do
|
|
39
39
|
User.create! do |u|
|
40
40
|
u.identity_url = "http://openid.example.org/myid"
|
41
41
|
end
|
42
|
+
|
43
|
+
LegacyUser.create! do |u|
|
44
|
+
u.identity_url = "http://openid.example.org/myid"
|
45
|
+
end
|
46
|
+
|
47
|
+
DatabaseUser.create! do |u|
|
48
|
+
u.email = "dbuser@example.com"
|
49
|
+
u.password = "password"
|
50
|
+
u.identity_url = "http://openid.example.org/myid"
|
51
|
+
end
|
42
52
|
end
|
43
53
|
|
44
54
|
after do
|
45
55
|
User.delete_all
|
56
|
+
LegacyUser.delete_all
|
57
|
+
DatabaseUser.delete_all
|
46
58
|
end
|
47
59
|
|
48
60
|
describe "GET /protected/resource" do
|
@@ -198,5 +210,123 @@ describe Devise::Strategies::OpenidAuthenticatable do
|
|
198
210
|
User.order(:id).last.email.should == 'dimitrij@example.com'
|
199
211
|
end
|
200
212
|
end
|
213
|
+
|
214
|
+
describe "POST /legacy_users/sign_in (from OpenID provider, success, new user)" do
|
215
|
+
|
216
|
+
before do
|
217
|
+
@previous_logger = Rails.logger
|
218
|
+
@log_output = StringIO.new
|
219
|
+
Rails.logger = Logger.new(@log_output)
|
220
|
+
|
221
|
+
@identity = 'http://openid.example.org/newid'
|
222
|
+
stub_completion
|
223
|
+
post '/legacy_users/sign_in', openid_params.merge("_method"=>"post")
|
224
|
+
end
|
225
|
+
|
226
|
+
after do
|
227
|
+
Rails.logger = @previous_logger
|
228
|
+
end
|
201
229
|
|
230
|
+
it 'should accept authentication with success' do
|
231
|
+
response.should be_redirect
|
232
|
+
response.should redirect_to('http://www.example.com/')
|
233
|
+
flash[:notice].should match(/success/i)
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'should auto-create user-records (if supported)' do
|
237
|
+
LegacyUser.should have(2).records
|
238
|
+
end
|
239
|
+
|
240
|
+
it 'should update new user-records with retrieved information' do
|
241
|
+
LegacyUser.order(:id).last.email.should == 'dimitrij@example.com'
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'should issue a deprecation warning' do
|
245
|
+
@log_output.string.should =~ /DEPRECATION WARNING: create_from_identity_url/
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
describe "POST /database_users/sign_in (using database authentication)" do
|
250
|
+
|
251
|
+
before do
|
252
|
+
post '/database_users/sign_in', :database_user => { :email => "dbuser@example.com", :password => "password" }
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'should accept authentication with success' do
|
256
|
+
response.should be_redirect
|
257
|
+
response.should redirect_to('http://www.example.com/')
|
258
|
+
flash[:notice].should match(/success/i)
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
|
263
|
+
describe "POST /database_users/sign_in (using OpenID, begin_authentication)" do
|
264
|
+
before do
|
265
|
+
Rack::OpenID.any_instance.stubs(:begin_authentication).returns([302, {'location' => 'http://openid.example.org/server'}, ''])
|
266
|
+
post '/database_users/sign_in', 'database_user' => { 'identity_url' => 'http://openid.example.org/myid' }
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'should forward request to provider' do
|
270
|
+
response.should be_redirect
|
271
|
+
response.should redirect_to('http://openid.example.org/server')
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
describe "POST /database_users/sign_in (using OpenID, from provider, existing user)" do
|
276
|
+
before do
|
277
|
+
stub_completion
|
278
|
+
post '/database_users/sign_in', openid_params.merge("_method"=>"post")
|
279
|
+
end
|
280
|
+
|
281
|
+
it 'should accept authentication with success' do
|
282
|
+
response.should be_redirect
|
283
|
+
response.should redirect_to('http://www.example.com/')
|
284
|
+
flash[:notice].should match(/success/i)
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'should update user-records with retrieved information' do
|
288
|
+
DatabaseUser.should have(1).record
|
289
|
+
DatabaseUser.first.email.should == 'dimitrij@example.com'
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
describe "POST /database_users/sign_in (using OpenID, from provider, existing email)" do
|
294
|
+
before do
|
295
|
+
DatabaseUser.delete_all
|
296
|
+
DatabaseUser.create! do |u|
|
297
|
+
u.email = "dimitrij@example.com"
|
298
|
+
u.password = "password"
|
299
|
+
end
|
300
|
+
|
301
|
+
stub_completion
|
302
|
+
post '/database_users/sign_in', openid_params.merge("_method"=>"post")
|
303
|
+
end
|
304
|
+
|
305
|
+
it 'should fail to authenticate with existing email error' do
|
306
|
+
response.should be_success
|
307
|
+
response.should render_template("sessions/new")
|
308
|
+
flash[:alert].should match(/email/i)
|
309
|
+
DatabaseUser.should have(1).record
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
describe "POST /database_users/sign_in (using OpenID, from provider, forgery attempt)" do
|
314
|
+
before do
|
315
|
+
DatabaseUser.delete_all
|
316
|
+
DatabaseUser.create! do |u|
|
317
|
+
u.email = "dimitrij@example.com"
|
318
|
+
u.password = "password"
|
319
|
+
u.identity_url = "http://openid.example.org/different_id"
|
320
|
+
end
|
321
|
+
|
322
|
+
stub_completion
|
323
|
+
post '/database_users/sign_in', openid_params.merge("_method"=>"post")
|
324
|
+
end
|
325
|
+
|
326
|
+
it 'should fail authentication with existing email error' do
|
327
|
+
response.should be_success
|
328
|
+
response.should render_template("sessions/new")
|
329
|
+
flash[:alert].should match(/email/i)
|
330
|
+
end
|
331
|
+
end
|
202
332
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise_openid_authenticatable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: -
|
4
|
+
hash: -1848230054
|
5
5
|
prerelease: true
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
9
|
- 0
|
10
|
-
-
|
11
|
-
version: 1.0.0.
|
10
|
+
- beta2
|
11
|
+
version: 1.0.0.beta2
|
12
12
|
platform: ruby
|
13
13
|
authors:
|
14
14
|
- Nat Budin
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-
|
19
|
+
date: 2010-12-21 00:00:00 -05:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -77,6 +77,8 @@ files:
|
|
77
77
|
- spec/scenario/app/controllers/application_controller.rb
|
78
78
|
- spec/scenario/app/controllers/home_controller.rb
|
79
79
|
- spec/scenario/app/controllers/sessions_controller.rb
|
80
|
+
- spec/scenario/app/models/database_user.rb
|
81
|
+
- spec/scenario/app/models/legacy_user.rb
|
80
82
|
- spec/scenario/app/models/user.rb
|
81
83
|
- spec/scenario/app/views/layouts/application.html.erb
|
82
84
|
- spec/scenario/app/views/sessions/new.html.erb
|
@@ -137,6 +139,8 @@ test_files:
|
|
137
139
|
- spec/scenario/app/controllers/application_controller.rb
|
138
140
|
- spec/scenario/app/controllers/home_controller.rb
|
139
141
|
- spec/scenario/app/controllers/sessions_controller.rb
|
142
|
+
- spec/scenario/app/models/database_user.rb
|
143
|
+
- spec/scenario/app/models/legacy_user.rb
|
140
144
|
- spec/scenario/app/models/user.rb
|
141
145
|
- spec/scenario/config/application.rb
|
142
146
|
- spec/scenario/config/boot.rb
|