stn-simple_token_authentication 1.7.1
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.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +270 -0
- data/Rakefile +61 -0
- data/doc/README.md +18 -0
- data/lib/simple_token_authentication.rb +58 -0
- data/lib/simple_token_authentication/acts_as_token_authenticatable.rb +49 -0
- data/lib/simple_token_authentication/acts_as_token_authentication_handler.rb +22 -0
- data/lib/simple_token_authentication/adapter.rb +7 -0
- data/lib/simple_token_authentication/adapters/active_record_adapter.rb +14 -0
- data/lib/simple_token_authentication/adapters/mongoid_adapter.rb +14 -0
- data/lib/simple_token_authentication/adapters/rails_adapter.rb +14 -0
- data/lib/simple_token_authentication/adapters/rails_api_adapter.rb +18 -0
- data/lib/simple_token_authentication/configuration.rb +45 -0
- data/lib/simple_token_authentication/entities_manager.rb +10 -0
- data/lib/simple_token_authentication/entity.rb +64 -0
- data/lib/simple_token_authentication/fallback_authentication_handler.rb +11 -0
- data/lib/simple_token_authentication/sign_in_handler.rb +19 -0
- data/lib/simple_token_authentication/token_authentication_handler.rb +149 -0
- data/lib/simple_token_authentication/token_comparator.rb +20 -0
- data/lib/simple_token_authentication/token_generator.rb +9 -0
- data/lib/simple_token_authentication/version.rb +3 -0
- data/lib/tasks/simple_token_authentication_tasks.rake +4 -0
- data/spec/configuration/action_controller_callbacks_options_spec.rb +53 -0
- data/spec/configuration/fallback_to_devise_option_spec.rb +128 -0
- data/spec/configuration/header_names_option_spec.rb +463 -0
- data/spec/configuration/sign_in_token_option_spec.rb +92 -0
- data/spec/lib/simple_token_authentication/acts_as_token_authenticatable_spec.rb +108 -0
- data/spec/lib/simple_token_authentication/acts_as_token_authentication_handler_spec.rb +127 -0
- data/spec/lib/simple_token_authentication/adapter_spec.rb +19 -0
- data/spec/lib/simple_token_authentication/adapters/active_record_adapter_spec.rb +21 -0
- data/spec/lib/simple_token_authentication/adapters/mongoid_adapter_spec.rb +21 -0
- data/spec/lib/simple_token_authentication/adapters/rails_adapter_spec.rb +21 -0
- data/spec/lib/simple_token_authentication/adapters/rails_api_adapter_spec.rb +43 -0
- data/spec/lib/simple_token_authentication/configuration_spec.rb +133 -0
- data/spec/lib/simple_token_authentication/entities_manager_spec.rb +67 -0
- data/spec/lib/simple_token_authentication/entity_spec.rb +190 -0
- data/spec/lib/simple_token_authentication/errors_spec.rb +8 -0
- data/spec/lib/simple_token_authentication/fallback_authentication_handler_spec.rb +24 -0
- data/spec/lib/simple_token_authentication/sign_in_handler_spec.rb +43 -0
- data/spec/lib/simple_token_authentication/token_authentication_handler_spec.rb +351 -0
- data/spec/lib/simple_token_authentication/token_comparator_spec.rb +19 -0
- data/spec/lib/simple_token_authentication/token_generator_spec.rb +19 -0
- data/spec/lib/simple_token_authentication_spec.rb +181 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/dummy_classes_helper.rb +80 -0
- data/spec/support/spec_for_adapter.rb +10 -0
- data/spec/support/spec_for_authentication_handler_interface.rb +8 -0
- data/spec/support/spec_for_configuration_option_interface.rb +28 -0
- data/spec/support/spec_for_entities_manager_interface.rb +8 -0
- data/spec/support/spec_for_sign_in_handler_interface.rb +8 -0
- data/spec/support/spec_for_token_comparator_interface.rb +8 -0
- data/spec/support/spec_for_token_generator_interface.rb +8 -0
- data/spec/support/specs_for_token_authentication_handler_interface.rb +8 -0
- metadata +250 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'ActionController', action_controller_callbacks_options: true do
|
4
|
+
|
5
|
+
after(:each) do
|
6
|
+
ensure_examples_independence
|
7
|
+
end
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
double_user_model
|
11
|
+
define_test_subjects_for_extension_of(SimpleTokenAuthentication::ActsAsTokenAuthenticationHandler)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe ':only option' do
|
15
|
+
|
16
|
+
context 'when provided to `acts_as_token_authentication_hanlder_for`' do
|
17
|
+
|
18
|
+
it 'is applied to the corresponding callback (1)', rspec_3_error: true, private: true do
|
19
|
+
some_class = @subjects.first
|
20
|
+
|
21
|
+
expect(some_class).to receive(:before_filter).with(:authenticate_user_from_token!, { only: ['some_action', :some_other_action] })
|
22
|
+
some_class.acts_as_token_authentication_handler_for User, only: ['some_action', :some_other_action]
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'is applied to the corresponding callback (2)', rspec_3_error: true, private: true do
|
26
|
+
some_child_class = @subjects.last
|
27
|
+
|
28
|
+
expect(some_child_class).to receive(:before_filter).with(:authenticate_user_from_token!, { only: ['some_action', :some_other_action] })
|
29
|
+
some_child_class.acts_as_token_authentication_handler_for User, only: ['some_action', :some_other_action]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe ':except option' do
|
35
|
+
|
36
|
+
context 'when provided to `acts_as_token_authentication_hanlder_for`' do
|
37
|
+
|
38
|
+
it 'is applied to the corresponding callback (1)', rspec_3_error: true, private: true do
|
39
|
+
some_class = @subjects.first
|
40
|
+
|
41
|
+
expect(some_class).to receive(:before_filter).with(:authenticate_user_from_token!, { except: ['some_action', :some_other_action] })
|
42
|
+
some_class.acts_as_token_authentication_handler_for User, except: ['some_action', :some_other_action]
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'is applied to the corresponding callback (2)', rspec_3_error: true, private: true do
|
46
|
+
some_child_class = @subjects.last
|
47
|
+
|
48
|
+
expect(some_child_class).to receive(:before_filter).with(:authenticate_user_from_token!, { except: ['some_action', :some_other_action] })
|
49
|
+
some_child_class.acts_as_token_authentication_handler_for User, except: ['some_action', :some_other_action]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Simple Token Authentication' do
|
4
|
+
|
5
|
+
describe ':fallback_to_devise option', fallback_to_devise_option: true, fallback_option: true do
|
6
|
+
|
7
|
+
describe 'determines what to do if token authentication fails' do
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
user = double()
|
11
|
+
stub_const('User', user)
|
12
|
+
allow(user).to receive(:name).and_return('User')
|
13
|
+
|
14
|
+
# given a controller class which acts as token authentication handler
|
15
|
+
@controller_class = Class.new
|
16
|
+
allow(@controller_class).to receive(:before_filter)
|
17
|
+
@controller_class.send :extend, SimpleTokenAuthentication::ActsAsTokenAuthenticationHandler
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when true' do
|
21
|
+
|
22
|
+
it 'delegates authentication to Devise strategies', protected: true do
|
23
|
+
@controller = @controller_class.new
|
24
|
+
allow(@controller).to receive(:params)
|
25
|
+
allow(@controller).to receive(:find_record_from_identifier)
|
26
|
+
|
27
|
+
# sets :authenticate_user_from_token! (bang) in the before_filter
|
28
|
+
expect(@controller_class).to receive(:before_filter).with(:authenticate_user_from_token!, {})
|
29
|
+
|
30
|
+
# when falling back to Devise is enabled
|
31
|
+
@controller_class.acts_as_token_authentication_handler_for User, fallback_to_devise: true
|
32
|
+
|
33
|
+
# when the hook is triggered
|
34
|
+
# Devise strategies take control of authentication
|
35
|
+
expect(@controller).to receive(:authenticate_user!)
|
36
|
+
@controller.authenticate_user_from_token! # bang
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when false' do
|
41
|
+
|
42
|
+
it 'does nothing after token authentication fails', protected: true do
|
43
|
+
@controller = @controller_class.new
|
44
|
+
allow(@controller).to receive(:params)
|
45
|
+
allow(@controller).to receive(:find_record_from_identifier)
|
46
|
+
|
47
|
+
# sets :authenticate_user_from_token (non-bang) in the before_filter
|
48
|
+
expect(@controller_class).to receive(:before_filter).with(:authenticate_user_from_token, {})
|
49
|
+
|
50
|
+
# when falling back to Devise is enabled
|
51
|
+
@controller_class.acts_as_token_authentication_handler_for User, fallback_to_devise: false
|
52
|
+
|
53
|
+
# when the hook is triggered
|
54
|
+
# Devise strategies do not take control of authentication
|
55
|
+
expect(@controller).not_to receive(:authenticate_user!)
|
56
|
+
@controller.authenticate_user_from_token # non-bang
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when omitted' do
|
61
|
+
|
62
|
+
it 'delegates authentication to Devise strategies', protected: true do
|
63
|
+
@controller = @controller_class.new
|
64
|
+
allow(@controller).to receive(:params)
|
65
|
+
allow(@controller).to receive(:find_record_from_identifier)
|
66
|
+
|
67
|
+
# sets :authenticate_user_from_token! (bang) in the before_filter
|
68
|
+
expect(@controller_class).to receive(:before_filter).with(:authenticate_user_from_token!, {})
|
69
|
+
|
70
|
+
# when falling back to Devise is enabled
|
71
|
+
@controller_class.acts_as_token_authentication_handler_for User
|
72
|
+
|
73
|
+
# when the hook is triggered
|
74
|
+
# Devise strategies take control of authentication
|
75
|
+
expect(@controller).to receive(:authenticate_user!)
|
76
|
+
@controller.authenticate_user_from_token! # bang
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'in a per-model (token authenticatable) way' do
|
81
|
+
|
82
|
+
before(:each) do
|
83
|
+
admin = double()
|
84
|
+
stub_const('Admin', admin)
|
85
|
+
allow(admin).to receive(:name).and_return('Admin')
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'when false for User and true for Admin' do
|
89
|
+
|
90
|
+
before(:each) do
|
91
|
+
@controller = @controller_class.new
|
92
|
+
allow(@controller).to receive(:params)
|
93
|
+
allow(@controller).to receive(:find_record_from_identifier)
|
94
|
+
|
95
|
+
# sets :authenticate_user_from_token (non-bang) in the before_filter
|
96
|
+
expect(@controller_class).to receive(:before_filter).with(:authenticate_user_from_token, {})
|
97
|
+
# sets :authenticate_admin_from_token! (bang) in the before_filter
|
98
|
+
expect(@controller_class).to receive(:before_filter).with(:authenticate_admin_from_token!, {})
|
99
|
+
|
100
|
+
# when falling back to Devise is enabled for Admin but not User
|
101
|
+
@controller_class.acts_as_token_authentication_handler_for User, fallback_to_devise: false
|
102
|
+
@controller_class.acts_as_token_authentication_handler_for Admin, fallback_to_devise: true
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'after no user suceeds token authentication' do
|
106
|
+
|
107
|
+
it 'does nothing', protected: true do
|
108
|
+
# when the user hook is triggered
|
109
|
+
# Devise strategies do not take control of authentication
|
110
|
+
expect(@controller).not_to receive(:authenticate_user!)
|
111
|
+
@controller.authenticate_user_from_token
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'after no admin succeeds token authentication' do
|
116
|
+
|
117
|
+
it 'does delegate authentication to Devise', protected: true do
|
118
|
+
# when the admin hook is triggered
|
119
|
+
# Devise strategies do take control of authentication
|
120
|
+
expect(@controller).to receive(:authenticate_admin!)
|
121
|
+
@controller.authenticate_admin_from_token!
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,463 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
def skip_devise_case_insensitive_keys_integration!(controller)
|
4
|
+
allow(controller).to receive(:integrate_with_devise_case_insensitive_keys) do |email|
|
5
|
+
email # return the email without modification
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'Simple Token Authentication' do
|
10
|
+
|
11
|
+
describe ':header_names option', header_names_option: true do
|
12
|
+
|
13
|
+
describe 'determines which header fields are looked at for authentication credentials' do
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
user = double()
|
17
|
+
stub_const('User', user)
|
18
|
+
allow(user).to receive(:name).and_return('User')
|
19
|
+
|
20
|
+
admin = double()
|
21
|
+
stub_const('Admin', admin)
|
22
|
+
allow(admin).to receive(:name).and_return('Admin')
|
23
|
+
|
24
|
+
# given one *c*orrect record (which is supposed to get signed in)
|
25
|
+
@charles_record = double()
|
26
|
+
[user, admin].each do |model|
|
27
|
+
allow(model).to receive(:where).with(email: 'charles@example.com').and_return([@charles_record])
|
28
|
+
end
|
29
|
+
allow(@charles_record).to receive(:authentication_token).and_return('ch4rlEs_toKeN')
|
30
|
+
|
31
|
+
# and one *w*rong record (which should not be signed in)
|
32
|
+
@waldo_record = double()
|
33
|
+
[user, admin].each do |model|
|
34
|
+
allow(model).to receive(:where).with(email: 'waldo@example.com').and_return([@waldo_record])
|
35
|
+
end
|
36
|
+
allow(@waldo_record).to receive(:authentication_token).and_return('w4LdO_toKeN')
|
37
|
+
|
38
|
+
# given a controller class which acts as token authentication handler
|
39
|
+
@controller_class = Class.new
|
40
|
+
allow(@controller_class).to receive(:before_filter)
|
41
|
+
@controller_class.send :extend, SimpleTokenAuthentication::ActsAsTokenAuthenticationHandler
|
42
|
+
|
43
|
+
@controller = @controller_class.new
|
44
|
+
allow(@controller).to receive(:sign_in_handler).and_return(:sign_in_handler)
|
45
|
+
skip_devise_case_insensitive_keys_integration!(@controller)
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
context 'provided the controller handles authentication for User' do
|
50
|
+
|
51
|
+
before(:each) do
|
52
|
+
# and handles authentication for a given model
|
53
|
+
@controller_class.acts_as_token_authentication_handler_for User
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'and params contains no authentication credentials' do
|
57
|
+
|
58
|
+
before(:each) do
|
59
|
+
# and there are no credentials in params
|
60
|
+
allow(@controller).to receive(:params).and_return({})
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'and request headers contain credentials in the custom and default fields' do
|
64
|
+
|
65
|
+
before(:each) do
|
66
|
+
# request headers are set in the nested contexts, these are minor settings
|
67
|
+
allow(@controller).to receive_message_chain(:request, :headers).and_return(double())
|
68
|
+
allow(@controller).to receive(:sign_in_handler).and_return(:sign_in_handler)
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when {}' do
|
72
|
+
|
73
|
+
before(:each) do
|
74
|
+
# and credentials in the default header fields lead to the wrong record
|
75
|
+
allow(@controller.request.headers).to receive(:[]).with('X-CustomEmail')
|
76
|
+
.and_return('waldo@example.com')
|
77
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Admin-Email')
|
78
|
+
.and_return('waldo@example.com')
|
79
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Custom_Token')
|
80
|
+
.and_return('w4LdO_toKeN')
|
81
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Admin-Token')
|
82
|
+
.and_return('w4LdO_toKeN')
|
83
|
+
# while credential in the custom header fields lead to the correct record
|
84
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Email')
|
85
|
+
.and_return('charles@example.com')
|
86
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Token')
|
87
|
+
.and_return('ch4rlEs_toKeN')
|
88
|
+
|
89
|
+
allow(SimpleTokenAuthentication).to receive(:header_names)
|
90
|
+
.and_return({})
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'does look for credentials in the default header fields (\'X-User-Email\' and \'X-User-Token\')', public: true do
|
94
|
+
expect(@controller).to receive(:perform_sign_in!).with(@charles_record, :sign_in_handler)
|
95
|
+
@controller.authenticate_user_from_token
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'ignores credentials in any other fields', public: true do
|
99
|
+
expect(@controller).not_to receive(:perform_sign_in!).with(@waldo_record, :sign_in_handler)
|
100
|
+
@controller.authenticate_user_from_token
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'when { user: {} }' do
|
105
|
+
|
106
|
+
before(:each) do
|
107
|
+
# and credentials in the default header fields lead to the wrong record
|
108
|
+
allow(@controller.request.headers).to receive(:[]).with('X-CustomEmail')
|
109
|
+
.and_return('waldo@example.com')
|
110
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Admin-Email')
|
111
|
+
.and_return('waldo@example.com')
|
112
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Custom_Token')
|
113
|
+
.and_return('w4LdO_toKeN')
|
114
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Admin-Token')
|
115
|
+
.and_return('w4LdO_toKeN')
|
116
|
+
# while credential in the custom header fields lead to the correct record
|
117
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Email')
|
118
|
+
.and_return('charles@example.com')
|
119
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Token')
|
120
|
+
.and_return('ch4rlEs_toKeN')
|
121
|
+
|
122
|
+
allow(SimpleTokenAuthentication).to receive(:header_names)
|
123
|
+
.and_return({ user: {} })
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'does look for credentials in the default header fields (\'X-User-Email\' and \'X-User-Token\')', protected: true do
|
127
|
+
expect(@controller).to receive(:perform_sign_in!).with(@charles_record, :sign_in_handler)
|
128
|
+
@controller.authenticate_user_from_token
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'ignores credentials in any other fields', protected: true do
|
132
|
+
expect(@controller).not_to receive(:perform_sign_in!).with(@waldo_record, :sign_in_handler)
|
133
|
+
@controller.authenticate_user_from_token
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'when { user: { email: \'X-CustomEmail\', authentication_token: \'X-Custom_Token\' } }' do
|
138
|
+
|
139
|
+
before(:each) do
|
140
|
+
# and credentials in the default header fields lead to the wrong record
|
141
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Email')
|
142
|
+
.and_return('waldo@example.com')
|
143
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Token')
|
144
|
+
.and_return('w4LdO_toKeN')
|
145
|
+
# while credential in the custom header fields lead to the correct record
|
146
|
+
allow(@controller.request.headers).to receive(:[]).with('X-CustomEmail')
|
147
|
+
.and_return('charles@example.com')
|
148
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Custom_Token')
|
149
|
+
.and_return('ch4rlEs_toKeN')
|
150
|
+
|
151
|
+
allow(SimpleTokenAuthentication).to receive(:header_names)
|
152
|
+
.and_return({ user: { email: 'X-CustomEmail',
|
153
|
+
authentication_token: 'X-Custom_Token' } })
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'does look for credentials in the custom headers fields', public: true do
|
157
|
+
expect(@controller).to receive(:perform_sign_in!).with(@charles_record, :sign_in_handler)
|
158
|
+
@controller.authenticate_user_from_token
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'ignores credentials in any other fields (including default ones)', public: true do
|
162
|
+
expect(@controller).not_to receive(:perform_sign_in!).with(@waldo_record, :sign_in_handler)
|
163
|
+
@controller.authenticate_user_from_token
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context 'when { admin: { email: \'X-CustomEmail\', authentication_token: \'X-Custom_Token\' } }' do
|
168
|
+
|
169
|
+
before(:each) do
|
170
|
+
# and credentials in the default header fields lead to the wrong record
|
171
|
+
allow(@controller.request.headers).to receive(:[]).with('X-CustomEmail')
|
172
|
+
.and_return('waldo@example.com')
|
173
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Custom_Token')
|
174
|
+
.and_return('w4LdO_toKeN')
|
175
|
+
# while credential in the custom header fields lead to the correct record
|
176
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Email')
|
177
|
+
.and_return('charles@example.com')
|
178
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Token')
|
179
|
+
.and_return('ch4rlEs_toKeN')
|
180
|
+
|
181
|
+
allow(SimpleTokenAuthentication).to receive(:header_names)
|
182
|
+
.and_return({ admin: { email: 'X-CustomEmail',
|
183
|
+
authentication_token: 'X-Custom_Token' } })
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'does look for credentials in the default header fields for :user', public: true do
|
187
|
+
expect(@controller).to receive(:perform_sign_in!).with(@charles_record, :sign_in_handler)
|
188
|
+
@controller.authenticate_user_from_token
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'ignores credentials in the custom :admin header fields', public: true do
|
192
|
+
expect(@controller).not_to receive(:perform_sign_in!).with(@waldo_record, :sign_in_handler)
|
193
|
+
@controller.authenticate_user_from_token
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context 'when { user: { email: \'X-CustomEmail\' }, admin: { authentication_token: \'X-Custom_Token\' } }' do
|
198
|
+
|
199
|
+
before(:each) do
|
200
|
+
# and credentials in the default header fields lead to the wrong record
|
201
|
+
allow(@controller.request.headers).to receive(:[]).with(nil)
|
202
|
+
.and_return(nil)
|
203
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Admin-Email')
|
204
|
+
.and_return('waldo@example.com')
|
205
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Custom_Token')
|
206
|
+
.and_return('w4LdO_toKeN')
|
207
|
+
# while credential in the custom header fields lead to the correct record
|
208
|
+
allow(@controller.request.headers).to receive(:[]).with('X-CustomEmail')
|
209
|
+
.and_return('charles@example.com')
|
210
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Token')
|
211
|
+
.and_return('ch4rlEs_toKeN')
|
212
|
+
|
213
|
+
allow(SimpleTokenAuthentication).to receive(:header_names)
|
214
|
+
.and_return({ user: { email: 'X-CustomEmail' },
|
215
|
+
admin: { authentication_token: 'X-Custom_Token' } })
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'does look for credentials in \'X-CustomEmail\' and \'X-User-Token\'', public: true do
|
219
|
+
expect(@controller).to receive(:perform_sign_in!).with(@charles_record, :sign_in_handler)
|
220
|
+
@controller.authenticate_user_from_token
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'ignores credentials in \'X-User-Email\' and the :admin header fields', public: true do
|
224
|
+
expect(@controller).not_to receive(:perform_sign_in!).with(@waldo_record, :sign_in_handler)
|
225
|
+
@controller.authenticate_user_from_token
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context 'when { admin: { email: \'X-CustomEmail\' }, user: { authentication_token: \'X-Custom_Token\' } }' do
|
230
|
+
|
231
|
+
before(:each) do
|
232
|
+
# and credentials in the default header fields lead to the wrong record
|
233
|
+
allow(@controller.request.headers).to receive(:[]).with(nil)
|
234
|
+
.and_return(nil)
|
235
|
+
allow(@controller.request.headers).to receive(:[]).with('X-CustomEmail')
|
236
|
+
.and_return('waldo@example.com')
|
237
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Admin-Email')
|
238
|
+
.and_return('waldo@example.com')
|
239
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Custom_Token')
|
240
|
+
.and_return('w4LdO_toKeN')
|
241
|
+
# while credential in the custom header fields lead to the correct record
|
242
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Email')
|
243
|
+
.and_return('charles@example.com')
|
244
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Custom_Token')
|
245
|
+
.and_return('ch4rlEs_toKeN')
|
246
|
+
|
247
|
+
allow(SimpleTokenAuthentication).to receive(:header_names)
|
248
|
+
.and_return({ admin: { email: 'X-CustomEmail' },
|
249
|
+
user: { authentication_token: 'X-Custom_Token' } })
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'does look for credentials in \'X-User-Email\' and \'X-Custom_Token\'', public: true do
|
253
|
+
expect(@controller).to receive(:perform_sign_in!).with(@charles_record, :sign_in_handler)
|
254
|
+
@controller.authenticate_user_from_token
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'ignores credentials in \'X-User-Token\' and the :admin header fields', public: true do
|
258
|
+
expect(@controller).not_to receive(:perform_sign_in!).with(@waldo_record, :sign_in_handler)
|
259
|
+
@controller.authenticate_user_from_token
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
context 'when { user: { email: \'X-CustomEmail\' } }' do
|
264
|
+
|
265
|
+
before(:each) do
|
266
|
+
# and credentials in the default header fields lead to the wrong record
|
267
|
+
allow(@controller).to receive_message_chain(:request, :headers).and_return(double())
|
268
|
+
allow(@controller.request.headers).to receive(:[]).with(nil)
|
269
|
+
.and_return(nil)
|
270
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Email')
|
271
|
+
.and_return('waldo@example.com')
|
272
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Admin-Email')
|
273
|
+
.and_return('waldo@example.com')
|
274
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Admin-Token')
|
275
|
+
.and_return('w4LdO_toKeN')
|
276
|
+
# while credential in the custom header fields lead to the correct record
|
277
|
+
allow(@controller.request.headers).to receive(:[]).with('X-CustomEmail')
|
278
|
+
.and_return('charles@example.com')
|
279
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Token')
|
280
|
+
.and_return('ch4rlEs_toKeN')
|
281
|
+
|
282
|
+
allow(SimpleTokenAuthentication).to receive(:header_names)
|
283
|
+
.and_return({ user: { email: 'X-CustomEmail' } })
|
284
|
+
end
|
285
|
+
|
286
|
+
it 'does look for credentials in \'X-CustomEmail\' and \'X-User-Token\'', public: true do
|
287
|
+
expect(@controller).to receive(:perform_sign_in!).with(@charles_record, :sign_in_handler)
|
288
|
+
@controller.authenticate_user_from_token
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'ignores credentials in \'X-User-Email\' and the :admin header fields', public: true do
|
292
|
+
expect(@controller).not_to receive(:perform_sign_in!).with(@waldo_record, :sign_in_handler)
|
293
|
+
@controller.authenticate_user_from_token
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
context 'provided the controller handles authentication for Admin' do
|
301
|
+
|
302
|
+
before(:each) do
|
303
|
+
# and handles authentication for a given model
|
304
|
+
@controller_class.acts_as_token_authentication_handler_for Admin
|
305
|
+
end
|
306
|
+
|
307
|
+
context 'and params contains no authentication credentials' do
|
308
|
+
|
309
|
+
before(:each) do
|
310
|
+
# and there are no credentials in params
|
311
|
+
allow(@controller).to receive(:params).and_return({})
|
312
|
+
end
|
313
|
+
|
314
|
+
context 'and request headers contain credentials in the custom and default fields' do
|
315
|
+
|
316
|
+
before(:each) do
|
317
|
+
# request headers are set in the nested contexts, these are minor settings
|
318
|
+
allow(@controller).to receive_message_chain(:request, :headers).and_return(double())
|
319
|
+
allow(@controller).to receive(:sign_in_handler).and_return(:sign_in_handler)
|
320
|
+
end
|
321
|
+
|
322
|
+
context 'when { admin: { email: \'X-CustomEmail\', authentication_token: \'X-Custom_Token\' } }' do
|
323
|
+
|
324
|
+
before(:each) do
|
325
|
+
# and credentials in the default header fields lead to the wrong record
|
326
|
+
allow(@controller).to receive_message_chain(:request, :headers).and_return(double())
|
327
|
+
allow(@controller.request.headers).to receive(:[]).with(nil)
|
328
|
+
.and_return(nil)
|
329
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Admin-Email')
|
330
|
+
.and_return('waldo@example.com')
|
331
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Email')
|
332
|
+
.and_return('waldo@example.com')
|
333
|
+
|
334
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Admin-Token')
|
335
|
+
.and_return('w4LdO_toKeN')
|
336
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Token')
|
337
|
+
.and_return('w4LdO_toKeN')
|
338
|
+
# while credential in the custom header fields lead to the correct record
|
339
|
+
allow(@controller.request.headers).to receive(:[]).with('X-CustomEmail')
|
340
|
+
.and_return('charles@example.com')
|
341
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Custom_Token')
|
342
|
+
.and_return('ch4rlEs_toKeN')
|
343
|
+
|
344
|
+
allow(SimpleTokenAuthentication).to receive(:header_names)
|
345
|
+
.and_return({ admin: { email: 'X-CustomEmail', authentication_token: 'X-Custom_Token' } })
|
346
|
+
end
|
347
|
+
|
348
|
+
it 'does look for credentials in \'X-CustomEmail\' and \'X-Custom_Token\'', public: true do
|
349
|
+
expect(@controller).to receive(:perform_sign_in!).with(@charles_record, :sign_in_handler)
|
350
|
+
@controller.authenticate_admin_from_token
|
351
|
+
end
|
352
|
+
|
353
|
+
it 'ignores credentials in \'X-Admin-Email\', \'X-Admin-Token\' and the :user header fields', public: true do
|
354
|
+
expect(@controller).not_to receive(:perform_sign_in!).with(@waldo_record, :sign_in_handler)
|
355
|
+
@controller.authenticate_admin_from_token
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
context 'when { admin: { email: \'X-CustomEmail\' } }' do
|
360
|
+
|
361
|
+
before(:each) do
|
362
|
+
# and credentials in the default header fields lead to the wrong record
|
363
|
+
allow(@controller).to receive_message_chain(:request, :headers).and_return(double())
|
364
|
+
allow(@controller.request.headers).to receive(:[]).with(nil)
|
365
|
+
.and_return(nil)
|
366
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Admin-Email')
|
367
|
+
.and_return('waldo@example.com')
|
368
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Email')
|
369
|
+
.and_return('waldo@example.com')
|
370
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Token')
|
371
|
+
.and_return('w4LdO_toKeN')
|
372
|
+
# while credential in the custom header fields lead to the correct record
|
373
|
+
allow(@controller.request.headers).to receive(:[]).with('X-CustomEmail')
|
374
|
+
.and_return('charles@example.com')
|
375
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Admin-Token')
|
376
|
+
.and_return('ch4rlEs_toKeN')
|
377
|
+
|
378
|
+
allow(SimpleTokenAuthentication).to receive(:header_names)
|
379
|
+
.and_return({ admin: { email: 'X-CustomEmail' } })
|
380
|
+
end
|
381
|
+
|
382
|
+
it 'does look for credentials in \'X-CustomEmail\' and \'X-Admin-Token\'', public: true do
|
383
|
+
expect(@controller).to receive(:perform_sign_in!).with(@charles_record, :sign_in_handler)
|
384
|
+
@controller.authenticate_admin_from_token
|
385
|
+
end
|
386
|
+
|
387
|
+
it 'ignores credentials in \'X-Admin-Email\' and the :user header fields', public: true do
|
388
|
+
expect(@controller).not_to receive(:perform_sign_in!).with(@waldo_record, :sign_in_handler)
|
389
|
+
@controller.authenticate_admin_from_token
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
it 'can be modified from an initializer file', public: true do
|
398
|
+
user = double()
|
399
|
+
stub_const('User', user)
|
400
|
+
allow(user).to receive(:name).and_return('User')
|
401
|
+
|
402
|
+
# given one *c*orrect record (which is supposed to get signed in)
|
403
|
+
@charles_record = double()
|
404
|
+
allow(user).to receive(:where).with(email: 'charles@example.com').and_return([@charles_record])
|
405
|
+
allow(@charles_record).to receive(:authentication_token).and_return('ch4rlEs_toKeN')
|
406
|
+
|
407
|
+
# and one *w*rong record (which should not be signed in)
|
408
|
+
@waldo_record = double()
|
409
|
+
allow(user).to receive(:where).with(email: 'waldo@example.com').and_return([@waldo_record])
|
410
|
+
allow(@waldo_record).to receive(:authentication_token).and_return('w4LdO_toKeN')
|
411
|
+
|
412
|
+
# given a controller class which acts as token authentication handler
|
413
|
+
@controller_class = Class.new
|
414
|
+
allow(@controller_class).to receive(:before_filter)
|
415
|
+
@controller_class.send :extend, SimpleTokenAuthentication::ActsAsTokenAuthenticationHandler
|
416
|
+
|
417
|
+
# INITIALIZATION
|
418
|
+
# this step occurs when 'simple_token_authentication' is required
|
419
|
+
#
|
420
|
+
# and handles authentication for a given model
|
421
|
+
@controller_class.acts_as_token_authentication_handler_for User
|
422
|
+
|
423
|
+
# RUNTIME
|
424
|
+
@controller = @controller_class.new
|
425
|
+
# and there are no credentials in params
|
426
|
+
allow(@controller).to receive(:params).and_return({})
|
427
|
+
# (those are minor settings)
|
428
|
+
allow(@controller).to receive_message_chain(:request, :headers).and_return(double())
|
429
|
+
allow(@controller).to receive(:sign_in_handler).and_return(:sign_in_handler)
|
430
|
+
allow(@controller).to receive(:perform_sign_in!)
|
431
|
+
|
432
|
+
# and credentials in the header fields which match
|
433
|
+
# the initial `header_names` option value
|
434
|
+
allow(@controller).to receive_message_chain(:request, :headers).and_return(double())
|
435
|
+
allow(@controller.request.headers).to receive(:[]).with('X-User-Email')
|
436
|
+
.and_return('waldo@example.com')
|
437
|
+
allow(@controller.request.headers).to receive(:[]).with('X-Custom_Token')
|
438
|
+
.and_return('w4LdO_toKeN')
|
439
|
+
|
440
|
+
# end credential in the header fields which match
|
441
|
+
# the updated `header_names` option value
|
442
|
+
allow(@controller.request.headers).to receive(:[]).with('X-UpdatedName-User-Email')
|
443
|
+
.and_return('charles@example.com')
|
444
|
+
allow(@controller.request.headers).to receive(:[]).with('X-UpdatedName-User-Token')
|
445
|
+
.and_return('ch4rlEs_toKeN')
|
446
|
+
|
447
|
+
|
448
|
+
# even if modified *after* the class was loaded
|
449
|
+
allow(SimpleTokenAuthentication).to receive(:header_names)
|
450
|
+
.and_return({ user: { email: 'X-UpdatedName-User-Email', authentication_token: 'X-UpdatedName-User-Token' }})
|
451
|
+
|
452
|
+
skip_devise_case_insensitive_keys_integration!(@controller)
|
453
|
+
|
454
|
+
# the option updated value is taken into account
|
455
|
+
# when token authentication is performed
|
456
|
+
expect(@controller.request.headers).to receive(:[]).with('X-UpdatedName-User-Email')
|
457
|
+
expect(@controller.request.headers).to receive(:[]).with('X-UpdatedName-User-Token')
|
458
|
+
expect(@controller.request.headers).not_to receive(:[]).with('X-User-Email')
|
459
|
+
expect(@controller.request.headers).not_to receive(:[]).with('X-User-Token')
|
460
|
+
@controller.authenticate_user_from_token
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|