simple_token_authentication 1.5.1 → 1.5.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|