simple_token_authentication 1.5.1 → 1.5.2
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 +4 -4
- data/README.md +23 -24
- data/Rakefile +31 -11
- data/doc/README.md +18 -0
- data/lib/simple_token_authentication.rb +39 -0
- data/lib/simple_token_authentication/acts_as_token_authenticatable.rb +18 -7
- data/lib/simple_token_authentication/acts_as_token_authentication_handler.rb +12 -123
- 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/rails_adapter.rb +14 -0
- data/lib/simple_token_authentication/configuration.rb +25 -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 +138 -0
- data/lib/simple_token_authentication/token_comparator.rb +13 -0
- data/lib/simple_token_authentication/token_generator.rb +9 -0
- data/lib/simple_token_authentication/version.rb +1 -1
- 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 +454 -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 +21 -0
- data/spec/lib/simple_token_authentication/adapters/active_record_adapter_spec.rb +21 -0
- data/spec/lib/simple_token_authentication/adapters/rails_adapter_spec.rb +21 -0
- data/spec/lib/simple_token_authentication/configuration_spec.rb +121 -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/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 +250 -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 +86 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/dummy_classes_helper.rb +80 -0
- data/spec/support/spec_for_adapter.rb +6 -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 +80 -132
- data/lib/tasks/cucumber.rake +0 -65
- data/spec/dummy/README.rdoc +0 -28
- data/spec/dummy/Rakefile +0 -6
- data/spec/dummy/app/assets/javascripts/application.js +0 -13
- data/spec/dummy/app/assets/stylesheets/application.css +0 -13
- data/spec/dummy/app/controllers/application_controller.rb +0 -5
- data/spec/dummy/app/helpers/application_helper.rb +0 -2
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/dummy/bin/bundle +0 -3
- data/spec/dummy/bin/rails +0 -4
- data/spec/dummy/bin/rake +0 -4
- data/spec/dummy/config.ru +0 -4
- data/spec/dummy/config/application.rb +0 -24
- data/spec/dummy/config/boot.rb +0 -5
- data/spec/dummy/config/database.yml +0 -25
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -29
- data/spec/dummy/config/environments/production.rb +0 -80
- data/spec/dummy/config/environments/test.rb +0 -36
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -4
- data/spec/dummy/config/initializers/inflections.rb +0 -16
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/secret_token.rb +0 -12
- data/spec/dummy/config/initializers/session_store.rb +0 -3
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/spec/dummy/config/locales/en.yml +0 -23
- data/spec/dummy/config/routes.rb +0 -56
- data/spec/dummy/public/404.html +0 -58
- data/spec/dummy/public/422.html +0 -58
- data/spec/dummy/public/500.html +0 -57
- data/spec/dummy/public/favicon.ico +0 -0
@@ -1,15 +1,40 @@
|
|
1
1
|
module SimpleTokenAuthentication
|
2
2
|
module Configuration
|
3
3
|
|
4
|
+
mattr_reader :fallback
|
4
5
|
mattr_accessor :header_names
|
5
6
|
mattr_accessor :sign_in_token
|
7
|
+
mattr_accessor :controller_adapters
|
8
|
+
mattr_accessor :model_adapters
|
6
9
|
|
7
10
|
# Default configuration
|
11
|
+
@@fallback = :devise
|
8
12
|
@@header_names = {}
|
9
13
|
@@sign_in_token = false
|
14
|
+
@@controller_adapters = ['rails']
|
15
|
+
@@model_adapters = ['active_record']
|
10
16
|
|
17
|
+
# Allow the default configuration to be overwritten from initializers
|
11
18
|
def configure
|
12
19
|
yield self if block_given?
|
13
20
|
end
|
21
|
+
|
22
|
+
def parse_options(options)
|
23
|
+
unless options[:fallback].presence
|
24
|
+
if options[:fallback_to_devise]
|
25
|
+
options[:fallback] = :devise
|
26
|
+
elsif options[:fallback_to_devise] == false
|
27
|
+
if SimpleTokenAuthentication.fallback == :devise
|
28
|
+
options[:fallback] = :none
|
29
|
+
else
|
30
|
+
options[:fallback] = SimpleTokenAuthentication.fallback
|
31
|
+
end
|
32
|
+
else
|
33
|
+
options[:fallback] = SimpleTokenAuthentication.fallback
|
34
|
+
end
|
35
|
+
end
|
36
|
+
options.reject! { |k,v| k == :fallback_to_devise }
|
37
|
+
options
|
38
|
+
end
|
14
39
|
end
|
15
40
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module SimpleTokenAuthentication
|
2
|
+
class Entity
|
3
|
+
def initialize model
|
4
|
+
@model = model
|
5
|
+
@name = model.name
|
6
|
+
end
|
7
|
+
|
8
|
+
def model
|
9
|
+
@model
|
10
|
+
end
|
11
|
+
|
12
|
+
def name
|
13
|
+
@name
|
14
|
+
end
|
15
|
+
|
16
|
+
def name_underscore
|
17
|
+
name.underscore
|
18
|
+
end
|
19
|
+
|
20
|
+
# Private: Return the name of the header to watch for the token authentication param
|
21
|
+
def token_header_name
|
22
|
+
if SimpleTokenAuthentication.header_names["#{name_underscore}".to_sym].presence \
|
23
|
+
&& token_header_name = SimpleTokenAuthentication.header_names["#{name_underscore}".to_sym][:authentication_token]
|
24
|
+
token_header_name
|
25
|
+
else
|
26
|
+
"X-#{name}-Token"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Private: Return the name of the header to watch for the email param
|
31
|
+
def identifier_header_name
|
32
|
+
if SimpleTokenAuthentication.header_names["#{name_underscore}".to_sym].presence \
|
33
|
+
&& identifier_header_name = SimpleTokenAuthentication.header_names["#{name_underscore}".to_sym][:email]
|
34
|
+
identifier_header_name
|
35
|
+
else
|
36
|
+
"X-#{name}-Email"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def token_param_name
|
41
|
+
"#{name_underscore}_token".to_sym
|
42
|
+
end
|
43
|
+
|
44
|
+
def identifier_param_name
|
45
|
+
"#{name_underscore}_email".to_sym
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_token_from_params_or_headers controller
|
49
|
+
# if the token is not present among params, get it from headers
|
50
|
+
if token = controller.params[token_param_name].blank? && controller.request.headers[token_header_name]
|
51
|
+
controller.params[token_param_name] = token
|
52
|
+
end
|
53
|
+
controller.params[token_param_name]
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_identifier_from_params_or_headers controller
|
57
|
+
# if the identifier (email) is not present among params, get it from headers
|
58
|
+
if email = controller.params[identifier_param_name].blank? && controller.request.headers[identifier_header_name]
|
59
|
+
controller.params[identifier_param_name] = email
|
60
|
+
end
|
61
|
+
controller.params[identifier_param_name]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module SimpleTokenAuthentication
|
2
|
+
class FallbackAuthenticationHandler
|
3
|
+
# Devise authentication is performed through a controller
|
4
|
+
# which includes Devise::Controllers::Helpers
|
5
|
+
# See http://rdoc.info/github/plataformatec/devise/master/\
|
6
|
+
# Devise/Controllers/Helpers#define_helpers-class_method
|
7
|
+
def authenticate_entity!(controller, entity)
|
8
|
+
controller.send("authenticate_#{entity.name_underscore}!".to_sym)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SimpleTokenAuthentication
|
2
|
+
class SignInHandler
|
3
|
+
# Devise sign in is performed through a controller
|
4
|
+
# which includes Devise::Controllers::SignInOut
|
5
|
+
def sign_in(controller, record, *args)
|
6
|
+
integrate_with_devise_trackable!(controller)
|
7
|
+
|
8
|
+
controller.send(:sign_in, record, *args)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def integrate_with_devise_trackable!(controller)
|
14
|
+
# Sign in using token should not be tracked by Devise trackable
|
15
|
+
# See https://github.com/plataformatec/devise/issues/953
|
16
|
+
controller.env["devise.skip_trackable"] = true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'action_controller/base'
|
2
|
+
require 'active_support/concern'
|
3
|
+
|
4
|
+
require 'simple_token_authentication/entities_manager'
|
5
|
+
require 'simple_token_authentication/fallback_authentication_handler'
|
6
|
+
require 'simple_token_authentication/sign_in_handler'
|
7
|
+
require 'simple_token_authentication/token_authentication_handler'
|
8
|
+
require 'simple_token_authentication/token_comparator'
|
9
|
+
|
10
|
+
module SimpleTokenAuthentication
|
11
|
+
module TokenAuthenticationHandler
|
12
|
+
extend ::ActiveSupport::Concern
|
13
|
+
|
14
|
+
included do
|
15
|
+
private_class_method :define_token_authentication_helpers_for
|
16
|
+
private_class_method :set_token_authentication_hooks
|
17
|
+
private_class_method :fallback_authentication_handler
|
18
|
+
|
19
|
+
private :authenticate_entity_from_token!
|
20
|
+
private :authenticate_entity_from_fallback!
|
21
|
+
private :token_correct?
|
22
|
+
private :perform_sign_in!
|
23
|
+
private :token_comparator
|
24
|
+
private :sign_in_handler
|
25
|
+
private :find_record_from_identifier
|
26
|
+
|
27
|
+
# This is necessary to test which arguments were passed to sign_in
|
28
|
+
# from authenticate_entity_from_token!
|
29
|
+
# See https://github.com/gonzalo-bulnes/simple_token_authentication/pull/32
|
30
|
+
::ActionController::Base.send :include, Devise::Controllers::SignInOut if Rails.env.test?
|
31
|
+
end
|
32
|
+
|
33
|
+
def authenticate_entity_from_token!(entity)
|
34
|
+
record = find_record_from_identifier(entity)
|
35
|
+
|
36
|
+
if token_correct?(record, entity, token_comparator)
|
37
|
+
perform_sign_in!(record, sign_in_handler)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def authenticate_entity_from_fallback!(entity, fallback_authentication_handler)
|
42
|
+
fallback_authentication_handler.authenticate_entity!(self, entity)
|
43
|
+
end
|
44
|
+
|
45
|
+
def token_correct?(record, entity, token_comparator)
|
46
|
+
record && token_comparator.compare(record.authentication_token,
|
47
|
+
entity.get_token_from_params_or_headers(self))
|
48
|
+
end
|
49
|
+
|
50
|
+
def perform_sign_in!(record, sign_in_handler)
|
51
|
+
# Notice the store option defaults to false, so the record
|
52
|
+
# identifier is not actually stored in the session and a token
|
53
|
+
# is needed for every request. That behaviour can be configured
|
54
|
+
# through the sign_in_token option.
|
55
|
+
sign_in_handler.sign_in self, record, store: SimpleTokenAuthentication.sign_in_token
|
56
|
+
end
|
57
|
+
|
58
|
+
def find_record_from_identifier(entity)
|
59
|
+
email = entity.get_identifier_from_params_or_headers(self).presence
|
60
|
+
|
61
|
+
# Rails 3 and 4 finder methods are supported,
|
62
|
+
# see https://github.com/ryanb/cancan/blob/1.6.10/lib/cancan/controller_resource.rb#L108-L111
|
63
|
+
record = nil
|
64
|
+
if entity.model.respond_to? "find_by"
|
65
|
+
record = email && entity.model.find_by(email: email)
|
66
|
+
elsif entity.model.respond_to? "find_by_email"
|
67
|
+
record = email && entity.model.find_by_email(email)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def token_comparator
|
72
|
+
@@token_comparator ||= TokenComparator.new
|
73
|
+
end
|
74
|
+
|
75
|
+
def sign_in_handler
|
76
|
+
@@sign_in_handler ||= SignInHandler.new
|
77
|
+
end
|
78
|
+
|
79
|
+
module ClassMethods
|
80
|
+
|
81
|
+
# Provide token authentication handling for a token authenticatable class
|
82
|
+
#
|
83
|
+
# model - the token authenticatable Class
|
84
|
+
#
|
85
|
+
# Returns nothing.
|
86
|
+
def handle_token_authentication_for(model, options = {})
|
87
|
+
entity = entities_manager.find_or_create_entity(model)
|
88
|
+
options = SimpleTokenAuthentication.parse_options(options)
|
89
|
+
define_token_authentication_helpers_for(entity, fallback_authentication_handler)
|
90
|
+
set_token_authentication_hooks(entity, options)
|
91
|
+
end
|
92
|
+
|
93
|
+
def entities_manager
|
94
|
+
if class_variable_defined?(:@@entities_manager)
|
95
|
+
class_variable_get(:@@entities_manager)
|
96
|
+
else
|
97
|
+
class_variable_set(:@@entities_manager, EntitiesManager.new)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def fallback_authentication_handler
|
102
|
+
if class_variable_defined?(:@@fallback_authentication_handler)
|
103
|
+
class_variable_get(:@@fallback_authentication_handler)
|
104
|
+
else
|
105
|
+
class_variable_set(:@@fallback_authentication_handler, FallbackAuthenticationHandler.new)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def define_token_authentication_helpers_for(entity, fallback_authentication_handler)
|
110
|
+
|
111
|
+
method_name = "authenticate_#{entity.name_underscore}_from_token"
|
112
|
+
method_name_bang = method_name + '!'
|
113
|
+
|
114
|
+
class_eval do
|
115
|
+
define_method method_name.to_sym do
|
116
|
+
lambda { |entity| authenticate_entity_from_token!(entity) }.call(entity)
|
117
|
+
end
|
118
|
+
|
119
|
+
define_method method_name_bang.to_sym do
|
120
|
+
lambda do |entity|
|
121
|
+
authenticate_entity_from_token!(entity)
|
122
|
+
authenticate_entity_from_fallback!(entity, fallback_authentication_handler)
|
123
|
+
end.call(entity)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def set_token_authentication_hooks(entity, options)
|
129
|
+
authenticate_method = unless options[:fallback] == :none
|
130
|
+
:"authenticate_#{entity.name_underscore}_from_token!"
|
131
|
+
else
|
132
|
+
:"authenticate_#{entity.name_underscore}_from_token"
|
133
|
+
end
|
134
|
+
before_filter authenticate_method, options.slice(:only, :except)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'devise'
|
2
|
+
|
3
|
+
module SimpleTokenAuthentication
|
4
|
+
class TokenComparator
|
5
|
+
def compare(a, b)
|
6
|
+
# Notice how we use Devise.secure_compare to compare tokens
|
7
|
+
# while mitigating timing attacks.
|
8
|
+
# See http://rubydoc.info/github/plataformatec/\
|
9
|
+
# devise/master/Devise#secure_compare-class_method
|
10
|
+
Devise.secure_compare(a, b)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -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
|