devise_openid_authenticatable 1.0.0.alpha7 → 1.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|