sorcery 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sorcery might be problematic. Click here for more details.

Files changed (83) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE.md +20 -0
  3. data/.rubocop.yml +52 -2
  4. data/.rubocop_todo.yml +1 -429
  5. data/.travis.yml +11 -21
  6. data/CHANGELOG.md +16 -0
  7. data/Gemfile +2 -2
  8. data/{LICENSE.txt → LICENSE.md} +1 -1
  9. data/README.md +7 -1
  10. data/gemfiles/{active_record-rails40.gemfile → active_record_rails_40.gemfile} +1 -2
  11. data/gemfiles/{active_record-rails41.gemfile → active_record_rails_41.gemfile} +1 -2
  12. data/gemfiles/{active_record-rails42.gemfile → active_record_rails_42.gemfile} +1 -2
  13. data/lib/generators/sorcery/USAGE +1 -1
  14. data/lib/generators/sorcery/install_generator.rb +21 -21
  15. data/lib/generators/sorcery/templates/initializer.rb +19 -1
  16. data/lib/sorcery/adapters/active_record_adapter.rb +1 -1
  17. data/lib/sorcery/adapters/mongoid_adapter.rb +23 -11
  18. data/lib/sorcery/controller.rb +22 -16
  19. data/lib/sorcery/controller/config.rb +2 -0
  20. data/lib/sorcery/controller/submodules/activity_logging.rb +4 -0
  21. data/lib/sorcery/controller/submodules/external.rb +37 -33
  22. data/lib/sorcery/controller/submodules/http_basic_auth.rb +1 -0
  23. data/lib/sorcery/controller/submodules/remember_me.rb +1 -7
  24. data/lib/sorcery/controller/submodules/session_timeout.rb +25 -4
  25. data/lib/sorcery/crypto_providers/aes256.rb +1 -0
  26. data/lib/sorcery/crypto_providers/bcrypt.rb +2 -1
  27. data/lib/sorcery/engine.rb +10 -3
  28. data/lib/sorcery/model.rb +9 -6
  29. data/lib/sorcery/model/config.rb +3 -3
  30. data/lib/sorcery/model/submodules/brute_force_protection.rb +6 -7
  31. data/lib/sorcery/model/submodules/external.rb +4 -3
  32. data/lib/sorcery/model/submodules/magic_login.rb +29 -36
  33. data/lib/sorcery/model/submodules/reset_password.rb +5 -4
  34. data/lib/sorcery/model/submodules/user_activation.rb +1 -1
  35. data/lib/sorcery/protocols/oauth.rb +1 -0
  36. data/lib/sorcery/providers/auth0.rb +46 -0
  37. data/lib/sorcery/providers/heroku.rb +1 -0
  38. data/lib/sorcery/providers/instagram.rb +73 -0
  39. data/lib/sorcery/providers/linkedin.rb +1 -1
  40. data/lib/sorcery/providers/vk.rb +1 -1
  41. data/lib/sorcery/providers/wechat.rb +8 -6
  42. data/lib/sorcery/test_helpers/internal.rb +5 -4
  43. data/lib/sorcery/test_helpers/internal/rails.rb +11 -11
  44. data/lib/sorcery/version.rb +1 -1
  45. data/sorcery.gemspec +25 -9
  46. data/spec/active_record/user_activation_spec.rb +2 -2
  47. data/spec/active_record/user_activity_logging_spec.rb +2 -2
  48. data/spec/active_record/user_brute_force_protection_spec.rb +2 -2
  49. data/spec/active_record/user_magic_login_spec.rb +4 -4
  50. data/spec/active_record/user_oauth_spec.rb +2 -2
  51. data/spec/active_record/user_remember_me_spec.rb +2 -2
  52. data/spec/active_record/user_reset_password_spec.rb +2 -2
  53. data/spec/active_record/user_spec.rb +0 -10
  54. data/spec/controllers/controller_http_basic_auth_spec.rb +1 -1
  55. data/spec/controllers/controller_oauth2_spec.rb +195 -123
  56. data/spec/controllers/controller_oauth_spec.rb +7 -7
  57. data/spec/controllers/controller_remember_me_spec.rb +11 -6
  58. data/spec/controllers/controller_session_timeout_spec.rb +90 -3
  59. data/spec/controllers/controller_spec.rb +2 -2
  60. data/spec/orm/active_record.rb +2 -2
  61. data/spec/providers/vk_spec.rb +13 -12
  62. data/spec/rails_app/app/controllers/sorcery_controller.rb +83 -32
  63. data/spec/rails_app/app/mailers/sorcery_mailer.rb +1 -1
  64. data/spec/rails_app/config/application.rb +8 -3
  65. data/spec/rails_app/config/boot.rb +1 -1
  66. data/spec/rails_app/config/environment.rb +1 -1
  67. data/spec/rails_app/config/routes.rb +7 -0
  68. data/spec/rails_app/config/secrets.yml +4 -0
  69. data/spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +2 -2
  70. data/spec/rails_app/db/migrate/invalidate_active_sessions/20180221093235_add_invalidate_active_sessions_before_to_users.rb +9 -0
  71. data/spec/rails_app/db/migrate/magic_login/20170924151831_add_magic_login_to_users.rb +3 -3
  72. data/spec/rails_app/db/schema.rb +7 -9
  73. data/spec/shared_examples/user_magic_login_shared_examples.rb +50 -50
  74. data/spec/shared_examples/user_oauth_shared_examples.rb +1 -1
  75. data/spec/shared_examples/user_remember_me_shared_examples.rb +1 -1
  76. data/spec/shared_examples/user_reset_password_shared_examples.rb +3 -3
  77. data/spec/shared_examples/user_shared_examples.rb +41 -43
  78. data/spec/sorcery_crypto_providers_spec.rb +1 -1
  79. data/spec/spec.opts +1 -1
  80. data/spec/spec_helper.rb +2 -2
  81. data/spec/support/migration_helper.rb +19 -0
  82. metadata +60 -38
  83. data/spec/rails_app/config/initializers/secret_token.rb +0 -7
@@ -40,12 +40,13 @@ module Sorcery
40
40
  def load_from_provider(provider, uid)
41
41
  config = sorcery_config
42
42
  authentication = config.authentications_class.sorcery_adapter.find_by_oauth_credentials(provider, uid)
43
- user = sorcery_adapter.find_by_id(authentication.send(config.authentications_user_id_attribute_name)) if authentication
43
+ # Return user if matching authentication found
44
+ sorcery_adapter.find_by_id(authentication.send(config.authentications_user_id_attribute_name)) if authentication
44
45
  end
45
46
 
46
47
  def create_and_validate_from_provider(provider, uid, attrs)
47
48
  user = new(attrs)
48
- user.send(sorcery_config.authentications_class.to_s.downcase.pluralize).build(
49
+ user.send(sorcery_config.authentications_class.name.demodulize.underscore.pluralize).build(
49
50
  sorcery_config.provider_uid_attribute_name => uid,
50
51
  sorcery_config.provider_attribute_name => provider
51
52
  )
@@ -92,7 +93,7 @@ module Sorcery
92
93
 
93
94
  module InstanceMethods
94
95
  def add_provider_to_user(provider, uid)
95
- authentications = sorcery_config.authentications_class.name.underscore.pluralize
96
+ authentications = sorcery_config.authentications_class.name.demodulize.underscore.pluralize
96
97
  # first check to see if user has a particular authentication already
97
98
  if sorcery_adapter.find_authentication_by_oauth_credentials(authentications, provider, uid).nil?
98
99
  user = send(authentications).build(sorcery_config.provider_uid_attribute_name => uid,
@@ -16,24 +16,18 @@ module Sorcery
16
16
  :magic_login_token_expires_at_attribute_name, # expires at attribute name.
17
17
  :magic_login_email_sent_at_attribute_name, # when was email sent, used for hammering
18
18
  # protection.
19
-
20
19
  :magic_login_mailer_class, # mailer class. Needed.
21
-
22
20
  :magic_login_mailer_disabled, # when true sorcery will not automatically
23
21
  # email magic login details and allow you to
24
22
  # manually handle how and when email is sent
25
-
26
23
  :magic_login_email_method_name, # magic login email method on your
27
24
  # mailer class.
28
-
29
25
  :magic_login_expiration_period, # how many seconds before the request
30
26
  # expires. nil for never expires.
31
-
32
27
  :magic_login_time_between_emails # hammering protection, how long to wait
33
28
  # before allowing another email to be sent.
34
-
35
29
  end
36
-
30
+
37
31
  base.sorcery_config.instance_eval do
38
32
  @defaults.merge!(:@magic_login_token_attribute_name => :magic_login_token,
39
33
  :@magic_login_token_expires_at_attribute_name => :magic_login_token_expires_at,
@@ -43,19 +37,18 @@ module Sorcery
43
37
  :@magic_login_email_method_name => :magic_login_email,
44
38
  :@magic_login_expiration_period => 15 * 60,
45
39
  :@magic_login_time_between_emails => 5 * 60)
46
-
40
+
47
41
  reset!
48
42
  end
49
-
43
+
50
44
  base.extend(ClassMethods)
51
-
45
+
52
46
  base.sorcery_config.after_config << :validate_mailer_defined
53
47
  base.sorcery_config.after_config << :define_magic_login_fields
54
-
48
+
55
49
  base.send(:include, InstanceMethods)
56
-
57
50
  end
58
-
51
+
59
52
  module ClassMethods
60
53
  # Find user by token, also checks for expiration.
61
54
  # Returns the user if token found and is valid.
@@ -64,44 +57,45 @@ module Sorcery
64
57
  token_expiration_date_attr = @sorcery_config.magic_login_token_expires_at_attribute_name
65
58
  load_from_token(token, token_attr_name, token_expiration_date_attr)
66
59
  end
67
-
60
+
68
61
  protected
69
-
62
+
70
63
  # This submodule requires the developer to define his own mailer class to be used by it
71
64
  # when magic_login_mailer_disabled is false
72
65
  def validate_mailer_defined
73
- msg = "To use magic_login submodule, you must define a mailer (config.magic_login_mailer_class = YourMailerClass)."
74
- raise ArgumentError, msg if @sorcery_config.magic_login_mailer_class.nil? and @sorcery_config.magic_login_mailer_disabled == false
66
+ msg = 'To use magic_login submodule, you must define a mailer (config.magic_login_mailer_class = YourMailerClass).'
67
+ raise ArgumentError, msg if @sorcery_config.magic_login_mailer_class.nil? && @sorcery_config.magic_login_mailer_disabled == false
75
68
  end
76
-
69
+
77
70
  def define_magic_login_fields
78
71
  sorcery_adapter.define_field sorcery_config.magic_login_token_attribute_name, String
79
72
  sorcery_adapter.define_field sorcery_config.magic_login_token_expires_at_attribute_name, Time
80
73
  sorcery_adapter.define_field sorcery_config.magic_login_email_sent_at_attribute_name, Time
81
74
  end
82
-
83
75
  end
84
-
76
+
85
77
  module InstanceMethods
86
78
  # generates a reset code with expiration
87
79
  def generate_magic_login_token!
88
80
  config = sorcery_config
89
- attributes = {config.magic_login_token_attribute_name => TemporaryToken.generate_random_token,
90
- config.magic_login_email_sent_at_attribute_name => Time.now.in_time_zone}
81
+ attributes = {
82
+ config.magic_login_token_attribute_name => TemporaryToken.generate_random_token,
83
+ config.magic_login_email_sent_at_attribute_name => Time.now.in_time_zone
84
+ }
91
85
  attributes[config.magic_login_token_expires_at_attribute_name] = Time.now.in_time_zone + config.magic_login_expiration_period if config.magic_login_expiration_period
92
-
93
- self.sorcery_adapter.update_attributes(attributes)
86
+
87
+ sorcery_adapter.update_attributes(attributes)
94
88
  end
95
-
89
+
96
90
  # generates a magic login code with expiration and sends an email to the user.
97
91
  def deliver_magic_login_instructions!
98
92
  mail = false
99
93
  config = sorcery_config
100
94
  # hammering protection
101
95
  return false if !config.magic_login_time_between_emails.nil? &&
102
- self.send(config.magic_login_email_sent_at_attribute_name) &&
103
- self.send(config.magic_login_email_sent_at_attribute_name) > config.magic_login_time_between_emails.seconds.ago
104
-
96
+ send(config.magic_login_email_sent_at_attribute_name) &&
97
+ send(config.magic_login_email_sent_at_attribute_name) > config.magic_login_time_between_emails.seconds.ago
98
+
105
99
  self.class.sorcery_adapter.transaction do
106
100
  generate_magic_login_token!
107
101
  unless config.magic_login_mailer_disabled
@@ -111,23 +105,22 @@ module Sorcery
111
105
  end
112
106
  mail
113
107
  end
114
-
108
+
115
109
  # Clears the token.
116
110
  def clear_magic_login_token!
117
111
  config = sorcery_config
118
- self.sorcery_adapter.update_attributes({
119
- config.magic_login_token_attribute_name => nil,
120
- config.magic_login_token_expires_at_attribute_name => nil
121
- })
112
+ sorcery_adapter.update_attributes(
113
+ config.magic_login_token_attribute_name => nil,
114
+ config.magic_login_token_expires_at_attribute_name => nil
115
+ )
122
116
  end
123
-
117
+
124
118
  protected
125
-
119
+
126
120
  def send_magic_login_email!
127
121
  generic_send_email(:magic_login_email_method_name, :magic_login_mailer_class)
128
122
  end
129
123
  end
130
-
131
124
  end
132
125
  end
133
126
  end
@@ -101,20 +101,21 @@ module Sorcery
101
101
  config = sorcery_config
102
102
  # hammering protection
103
103
  return false if config.reset_password_time_between_emails.present? && send(config.reset_password_email_sent_at_attribute_name) && send(config.reset_password_email_sent_at_attribute_name) > config.reset_password_time_between_emails.seconds.ago.utc
104
+
104
105
  self.class.sorcery_adapter.transaction do
105
106
  generate_reset_password_token!
106
107
  mail = send_reset_password_email! unless config.reset_password_mailer_disabled
107
108
  end
108
109
  mail
109
110
  end
110
-
111
+
111
112
  # Increment access_count_to_reset_password_page attribute.
112
113
  # For example, access_count_to_reset_password_page attribute is over 1, which
113
114
  # means the user doesn't have a right to access.
114
115
  def increment_password_reset_page_access_counter
115
- sorcery_adapter.increment(self.sorcery_config.reset_password_page_access_count_attribute_name)
116
+ sorcery_adapter.increment(sorcery_config.reset_password_page_access_count_attribute_name)
116
117
  end
117
-
118
+
118
119
  # Reset access_count_to_reset_password_page attribute into 0.
119
120
  # This is expected to be used after sending an instruction email.
120
121
  def reset_password_reset_page_access_counter
@@ -126,7 +127,7 @@ module Sorcery
126
127
  def change_password!(new_password)
127
128
  clear_reset_password_token
128
129
  send(:"#{sorcery_config.password_attribute_name}=", new_password)
129
- sorcery_adapter.save
130
+ sorcery_adapter.save raise_on_failure: true
130
131
  end
131
132
 
132
133
  protected
@@ -45,7 +45,7 @@ module Sorcery
45
45
  # don't setup activation if no password supplied - this user is created automatically
46
46
  sorcery_adapter.define_callback :before, :create, :setup_activation, if: proc { |user| user.send(sorcery_config.password_attribute_name).present? }
47
47
  # don't send activation needed email if no crypted password created - this user is external (OAuth etc.)
48
- sorcery_adapter.define_callback :after, :create, :send_activation_needed_email!, if: :send_activation_needed_email?
48
+ sorcery_adapter.define_callback :after, :commit, :send_activation_needed_email!, on: :create, if: :send_activation_needed_email?
49
49
  end
50
50
 
51
51
  base.sorcery_config.after_config << :validate_mailer_defined
@@ -9,6 +9,7 @@ module Sorcery
9
9
 
10
10
  def get_request_token(token = nil, secret = nil)
11
11
  return ::OAuth::RequestToken.new(get_consumer, token, secret) if token && secret
12
+
12
13
  get_consumer.get_request_token(oauth_callback: @callback_url)
13
14
  end
14
15
 
@@ -0,0 +1,46 @@
1
+ module Sorcery
2
+ module Providers
3
+ # This class adds support for OAuth with Auth0.com
4
+ #
5
+ # config.auth0.key = <key>
6
+ # config.auth0.secret = <secret>
7
+ # config.auth0.domain = <domain>
8
+ # ...
9
+ #
10
+ class Auth0 < Base
11
+ include Protocols::Oauth2
12
+
13
+ attr_accessor :auth_path, :token_path, :user_info_path, :scope
14
+
15
+ def initialize
16
+ super
17
+
18
+ @auth_path = '/authorize'
19
+ @token_path = '/oauth/token'
20
+ @user_info_path = '/userinfo'
21
+ @scope = 'openid profile email'
22
+ end
23
+
24
+ def get_user_hash(access_token)
25
+ response = access_token.get(user_info_path)
26
+
27
+ auth_hash(access_token).tap do |h|
28
+ h[:user_info] = JSON.parse(response.body)
29
+ h[:uid] = h[:user_info]['sub']
30
+ end
31
+ end
32
+
33
+ def login_url(_params, _session)
34
+ authorize_url(authorize_url: auth_path)
35
+ end
36
+
37
+ def process_callback(params, _session)
38
+ args = {}.tap do |a|
39
+ a[:code] = params[:code] if params[:code]
40
+ end
41
+
42
+ get_access_token(args, token_url: token_path, token_method: :post)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -45,6 +45,7 @@ module Sorcery
45
45
  # tries to login the user from access token
46
46
  def process_callback(params, _session)
47
47
  raise 'Invalid state. Potential Cross Site Forgery' if params[:state] != state
48
+
48
49
  args = {}.tap do |a|
49
50
  a[:code] = params[:code] if params[:code]
50
51
  end
@@ -0,0 +1,73 @@
1
+ module Sorcery
2
+ module Providers
3
+ # This class adds support for OAuth with Instagram.com.
4
+ class Instagram < Base
5
+ include Protocols::Oauth2
6
+
7
+ attr_accessor :access_permissions, :token_url,
8
+ :authorization_path, :user_info_path,
9
+ :scope, :user_info_fields
10
+
11
+ def initialize
12
+ super
13
+
14
+ @site = 'https://api.instagram.com'
15
+ @token_url = '/oauth/access_token'
16
+ @authorization_path = '/oauth/authorize/'
17
+ @user_info_path = '/v1/users/self'
18
+ @scope = 'basic'
19
+ end
20
+
21
+ def self.included(base)
22
+ base.extend Sorcery::Providers
23
+ end
24
+
25
+ # provider implements method to build Oauth client
26
+ def login_url(_params, _session)
27
+ authorize_url(token_url: @token_url)
28
+ end
29
+
30
+ # overrides oauth2#authorize_url to allow customized scope.
31
+ def authorize_url(opts = {})
32
+ @scope = access_permissions.present? ? access_permissions.join(' ') : scope
33
+ super(opts.merge(token_url: @token_url))
34
+ end
35
+
36
+ # pass oauth2 param `code` provided by instgrm server
37
+ def process_callback(params, _session)
38
+ args = {}.tap do |a|
39
+ a[:code] = params[:code] if params[:code]
40
+ end
41
+ get_access_token(
42
+ args,
43
+ token_url: @token_url,
44
+ client_id: @key,
45
+ client_secret: @secret
46
+ )
47
+ end
48
+
49
+ # see `user_info_mapping` in config/initializer,
50
+ # given `user_info_mapping` to specify
51
+ # {:db_attribute_name => 'instagram_attr_name'}
52
+ # so that Sorcery can build AR model from attr names
53
+ #
54
+ # NOTE: instead of just getting the user info
55
+ # from the access_token (which already returns them),
56
+ # testing strategy relies on querying user_info_path
57
+ def get_user_hash(access_token)
58
+ call_api_params = {
59
+ access_token: access_token.token,
60
+ client_id: access_token[:client_id]
61
+ }
62
+ response = access_token.get(
63
+ "#{user_info_path}?#{call_api_params.to_param}"
64
+ )
65
+
66
+ user_attrs = {}
67
+ user_attrs[:user_info] = JSON.parse(response.body)['data']
68
+ user_attrs[:uid] = user_attrs[:user_info]['id']
69
+ user_attrs
70
+ end
71
+ end
72
+ end
73
+ end
@@ -31,7 +31,7 @@ module Sorcery
31
31
 
32
32
  def get_user_hash(access_token)
33
33
  # Always include id for provider uid and prevent accidental duplication via setting `user_info_field = ['id']` (needed in Sorcery 0.9.1)
34
- info_fields = user_info_fields ? user_info_fields.reject{|n| n == 'id'} : []
34
+ info_fields = user_info_fields ? user_info_fields.reject { |n| n == 'id' } : []
35
35
  fields = info_fields.any? ? 'id,' + info_fields.join(',') : 'id'
36
36
  response = access_token.get("#{@user_info_path}:(#{fields})", 'x-li-format' => 'json')
37
37
 
@@ -33,7 +33,7 @@ module Sorcery
33
33
  }
34
34
 
35
35
  response = access_token.get(user_info_url, params: params)
36
- if user_hash[:user_info] = JSON.parse(response.body)
36
+ if (user_hash[:user_info] = JSON.parse(response.body))
37
37
  user_hash[:user_info] = user_hash[:user_info]['response'][0]
38
38
  user_hash[:user_info]['full_name'] = [user_hash[:user_info]['first_name'], user_hash[:user_info]['last_name']].join(' ')
39
39
 
@@ -37,10 +37,13 @@ module Sorcery
37
37
  end
38
38
 
39
39
  def get_user_hash(access_token)
40
- response = access_token.get(user_info_path, params: {
41
- access_token: access_token.token,
42
- openid: access_token.params['openid'],
43
- })
40
+ response = access_token.get(
41
+ user_info_path,
42
+ params: {
43
+ access_token: access_token.token,
44
+ openid: access_token.params['openid']
45
+ }
46
+ )
44
47
 
45
48
  {}.tap do |h|
46
49
  h[:user_info] = JSON.parse(response.body)
@@ -70,10 +73,9 @@ module Sorcery
70
73
  args,
71
74
  token_url: token_url,
72
75
  mode: mode,
73
- param_name: param_name,
76
+ param_name: param_name
74
77
  )
75
78
  end
76
79
  end
77
80
  end
78
81
  end
79
-
@@ -17,7 +17,7 @@ module Sorcery
17
17
  # a patch to fix a bug in testing that happens when you 'destroy' a session twice.
18
18
  # After the first destroy, the session is an ordinary hash, and then when destroy
19
19
  # is called again there's an exception.
20
- class ::Hash
20
+ class ::Hash # rubocop:disable Style/ClassAndModuleChildren
21
21
  def destroy
22
22
  clear
23
23
  end
@@ -69,9 +69,10 @@ module Sorcery
69
69
  def reload_user_class
70
70
  User && Object.send(:remove_const, 'User')
71
71
  load 'user.rb'
72
- if User.respond_to?(:reset_column_information)
73
- User.reset_column_information
74
- end
72
+
73
+ return unless User.respond_to?(:reset_column_information)
74
+
75
+ User.reset_column_information
75
76
  end
76
77
  end
77
78
  end
@@ -4,11 +4,11 @@ module Sorcery
4
4
  module Rails
5
5
  include ::Sorcery::TestHelpers::Rails::Controller
6
6
 
7
- SUBMODULES_AUTO_ADDED_CONTROLLER_FILTERS = [
8
- :register_last_activity_time_to_db,
9
- :deny_banned_user,
10
- :validate_session
11
- ]
7
+ SUBMODULES_AUTO_ADDED_CONTROLLER_FILTERS = %i[
8
+ register_last_activity_time_to_db
9
+ deny_banned_user
10
+ validate_session
11
+ ].freeze
12
12
 
13
13
  def sorcery_reload!(submodules = [], options = {})
14
14
  reload_user_class
@@ -40,11 +40,11 @@ module Sorcery
40
40
  end
41
41
  end
42
42
  User.authenticates_with_sorcery!
43
- if defined?(DataMapper) && User.ancestors.include?(DataMapper::Resource)
44
- DataMapper.auto_migrate!
45
- User.finalize
46
- Authentication.finalize
47
- end
43
+ return unless defined?(DataMapper) && User.ancestors.include?(DataMapper::Resource)
44
+
45
+ DataMapper.auto_migrate!
46
+ User.finalize
47
+ Authentication.finalize
48
48
  end
49
49
 
50
50
  def sorcery_controller_property_set(property, value)
@@ -64,7 +64,7 @@ module Sorcery
64
64
  end
65
65
 
66
66
  if ::Rails.version < '5.0.0'
67
- %w(get post put).each do |method|
67
+ %w[get post put].each do |method|
68
68
  define_method(method) do |action, options = {}|
69
69
  super action, options[:params] || {}, options[:session]
70
70
  end