sorcery 0.13.0 → 0.16.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 +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +5 -0
- data/.github/workflows/ruby.yml +49 -0
- data/.rubocop.yml +2 -2
- data/.rubocop_todo.yml +157 -1
- data/CHANGELOG.md +49 -0
- data/CODE_OF_CONDUCT.md +14 -0
- data/Gemfile +1 -1
- data/README.md +4 -4
- data/Rakefile +3 -1
- data/SECURITY.md +19 -0
- data/gemfiles/rails_52.gemfile +7 -0
- data/gemfiles/rails_60.gemfile +7 -0
- data/lib/generators/sorcery/helpers.rb +4 -0
- data/lib/generators/sorcery/templates/initializer.rb +111 -85
- data/lib/generators/sorcery/templates/migration/activity_logging.rb +5 -5
- data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +4 -4
- data/lib/generators/sorcery/templates/migration/core.rb +4 -4
- data/lib/generators/sorcery/templates/migration/external.rb +3 -3
- data/lib/generators/sorcery/templates/migration/magic_login.rb +4 -4
- data/lib/generators/sorcery/templates/migration/remember_me.rb +3 -3
- data/lib/generators/sorcery/templates/migration/reset_password.rb +5 -5
- data/lib/generators/sorcery/templates/migration/user_activation.rb +4 -4
- data/lib/sorcery/adapters/active_record_adapter.rb +2 -2
- data/lib/sorcery/controller.rb +4 -1
- data/lib/sorcery/controller/config.rb +6 -6
- data/lib/sorcery/controller/submodules/activity_logging.rb +5 -3
- data/lib/sorcery/controller/submodules/external.rb +4 -1
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +1 -0
- data/lib/sorcery/controller/submodules/remember_me.rb +2 -1
- data/lib/sorcery/controller/submodules/session_timeout.rb +2 -0
- data/lib/sorcery/crypto_providers/aes256.rb +1 -1
- data/lib/sorcery/crypto_providers/bcrypt.rb +6 -1
- data/lib/sorcery/engine.rb +7 -1
- data/lib/sorcery/model.rb +6 -5
- data/lib/sorcery/model/config.rb +5 -0
- data/lib/sorcery/model/submodules/magic_login.rb +7 -4
- data/lib/sorcery/model/submodules/reset_password.rb +6 -2
- data/lib/sorcery/providers/battlenet.rb +51 -0
- data/lib/sorcery/providers/discord.rb +52 -0
- data/lib/sorcery/providers/line.rb +63 -0
- data/lib/sorcery/providers/linkedin.rb +45 -36
- data/lib/sorcery/providers/vk.rb +1 -1
- data/lib/sorcery/version.rb +1 -1
- data/sorcery.gemspec +5 -6
- data/spec/controllers/controller_oauth2_spec.rb +41 -6
- data/spec/controllers/controller_oauth_spec.rb +6 -0
- data/spec/controllers/controller_remember_me_spec.rb +15 -12
- data/spec/controllers/controller_spec.rb +11 -1
- data/spec/providers/example_provider_spec.rb +17 -0
- data/spec/providers/example_spec.rb +17 -0
- data/spec/rails_app/app/assets/config/manifest.js +1 -0
- data/spec/rails_app/app/controllers/application_controller.rb +2 -0
- data/spec/rails_app/app/controllers/sorcery_controller.rb +69 -1
- data/spec/rails_app/config/routes.rb +10 -0
- data/spec/shared_examples/user_reset_password_shared_examples.rb +18 -2
- data/spec/shared_examples/user_shared_examples.rb +63 -0
- data/spec/sorcery_crypto_providers_spec.rb +60 -0
- data/spec/support/migration_helper.rb +12 -2
- data/spec/support/providers/example.rb +11 -0
- data/spec/support/providers/example_provider.rb +11 -0
- metadata +25 -15
- data/.travis.yml +0 -38
- data/gemfiles/active_record_rails_40.gemfile +0 -6
- data/gemfiles/active_record_rails_41.gemfile +0 -6
- data/gemfiles/active_record_rails_42.gemfile +0 -6
@@ -1,10 +1,10 @@
|
|
1
1
|
class SorceryActivityLogging < <%= migration_class_name %>
|
2
2
|
def change
|
3
|
-
add_column :<%=
|
4
|
-
add_column :<%=
|
5
|
-
add_column :<%=
|
6
|
-
add_column :<%=
|
3
|
+
add_column :<%= tableized_model_class %>, :last_login_at, :datetime, default: nil
|
4
|
+
add_column :<%= tableized_model_class %>, :last_logout_at, :datetime, default: nil
|
5
|
+
add_column :<%= tableized_model_class %>, :last_activity_at, :datetime, default: nil
|
6
|
+
add_column :<%= tableized_model_class %>, :last_login_from_ip_address, :string, default: nil
|
7
7
|
|
8
|
-
add_index :<%=
|
8
|
+
add_index :<%= tableized_model_class %>, [:last_logout_at, :last_activity_at]
|
9
9
|
end
|
10
10
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class SorceryBruteForceProtection < <%= migration_class_name %>
|
2
2
|
def change
|
3
|
-
add_column :<%=
|
4
|
-
add_column :<%=
|
5
|
-
add_column :<%=
|
3
|
+
add_column :<%= tableized_model_class %>, :failed_logins_count, :integer, default: 0
|
4
|
+
add_column :<%= tableized_model_class %>, :lock_expires_at, :datetime, default: nil
|
5
|
+
add_column :<%= tableized_model_class %>, :unlock_token, :string, default: nil
|
6
6
|
|
7
|
-
add_index :<%=
|
7
|
+
add_index :<%= tableized_model_class %>, :unlock_token
|
8
8
|
end
|
9
9
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
class SorceryCore < <%= migration_class_name %>
|
2
2
|
def change
|
3
|
-
create_table :<%=
|
4
|
-
t.string :email, :
|
3
|
+
create_table :<%= tableized_model_class %> do |t|
|
4
|
+
t.string :email, null: false
|
5
5
|
t.string :crypted_password
|
6
6
|
t.string :salt
|
7
7
|
|
8
|
-
t.timestamps :
|
8
|
+
t.timestamps null: false
|
9
9
|
end
|
10
10
|
|
11
|
-
add_index :<%=
|
11
|
+
add_index :<%= tableized_model_class %>, :email, unique: true
|
12
12
|
end
|
13
13
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
class SorceryExternal < <%= migration_class_name %>
|
2
2
|
def change
|
3
3
|
create_table :authentications do |t|
|
4
|
-
t.integer :<%=
|
5
|
-
t.string :provider, :uid, :
|
4
|
+
t.integer :<%= tableized_model_class.singularize %>_id, null: false
|
5
|
+
t.string :provider, :uid, null: false
|
6
6
|
|
7
|
-
t.timestamps :
|
7
|
+
t.timestamps null: false
|
8
8
|
end
|
9
9
|
|
10
10
|
add_index :authentications, [:provider, :uid]
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class SorceryMagicLogin < <%= migration_class_name %>
|
2
2
|
def change
|
3
|
-
add_column :<%=
|
4
|
-
add_column :<%=
|
5
|
-
add_column :<%=
|
3
|
+
add_column :<%= tableized_model_class %>, :magic_login_token, :string, default: nil
|
4
|
+
add_column :<%= tableized_model_class %>, :magic_login_token_expires_at, :datetime, default: nil
|
5
|
+
add_column :<%= tableized_model_class %>, :magic_login_email_sent_at, :datetime, default: nil
|
6
6
|
|
7
|
-
add_index :<%=
|
7
|
+
add_index :<%= tableized_model_class %>, :magic_login_token
|
8
8
|
end
|
9
9
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
class SorceryRememberMe < <%= migration_class_name %>
|
2
2
|
def change
|
3
|
-
add_column :<%=
|
4
|
-
add_column :<%=
|
3
|
+
add_column :<%= tableized_model_class %>, :remember_me_token, :string, default: nil
|
4
|
+
add_column :<%= tableized_model_class %>, :remember_me_token_expires_at, :datetime, default: nil
|
5
5
|
|
6
|
-
add_index :<%=
|
6
|
+
add_index :<%= tableized_model_class %>, :remember_me_token
|
7
7
|
end
|
8
8
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
class SorceryResetPassword < <%= migration_class_name %>
|
2
2
|
def change
|
3
|
-
add_column :<%=
|
4
|
-
add_column :<%=
|
5
|
-
add_column :<%=
|
6
|
-
add_column :<%=
|
3
|
+
add_column :<%= tableized_model_class %>, :reset_password_token, :string, default: nil
|
4
|
+
add_column :<%= tableized_model_class %>, :reset_password_token_expires_at, :datetime, default: nil
|
5
|
+
add_column :<%= tableized_model_class %>, :reset_password_email_sent_at, :datetime, default: nil
|
6
|
+
add_column :<%= tableized_model_class %>, :access_count_to_reset_password_page, :integer, default: 0
|
7
7
|
|
8
|
-
add_index :<%=
|
8
|
+
add_index :<%= tableized_model_class %>, :reset_password_token
|
9
9
|
end
|
10
10
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class SorceryUserActivation < <%= migration_class_name %>
|
2
2
|
def change
|
3
|
-
add_column :<%=
|
4
|
-
add_column :<%=
|
5
|
-
add_column :<%=
|
3
|
+
add_column :<%= tableized_model_class %>, :activation_state, :string, default: nil
|
4
|
+
add_column :<%= tableized_model_class %>, :activation_token, :string, default: nil
|
5
|
+
add_column :<%= tableized_model_class %>, :activation_token_expires_at, :datetime, default: nil
|
6
6
|
|
7
|
-
add_index :<%=
|
7
|
+
add_index :<%= tableized_model_class %>, :activation_token
|
8
8
|
end
|
9
9
|
end
|
@@ -12,7 +12,7 @@ module Sorcery
|
|
12
12
|
|
13
13
|
def save(options = {})
|
14
14
|
mthd = options.delete(:raise_on_failure) ? :save! : :save
|
15
|
-
@model.send(mthd, options)
|
15
|
+
@model.send(mthd, **options)
|
16
16
|
end
|
17
17
|
|
18
18
|
def increment(field)
|
@@ -35,7 +35,7 @@ module Sorcery
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def define_callback(time, event, method_name, options = {})
|
38
|
-
@klass.send "#{time}_#{event}", method_name, options.slice(:if, :on)
|
38
|
+
@klass.send "#{time}_#{event}", method_name, **options.slice(:if, :on)
|
39
39
|
end
|
40
40
|
|
41
41
|
def find_by_oauth_credentials(provider, uid)
|
data/lib/sorcery/controller.rb
CHANGED
@@ -25,7 +25,10 @@ module Sorcery
|
|
25
25
|
def require_login
|
26
26
|
return if logged_in?
|
27
27
|
|
28
|
-
|
28
|
+
if Config.save_return_to_url && request.get? && !request.xhr? && !request.format.json?
|
29
|
+
session[:return_to_url] = request.url
|
30
|
+
end
|
31
|
+
|
29
32
|
send(Config.not_authenticated_action)
|
30
33
|
end
|
31
34
|
|
@@ -25,12 +25,12 @@ module Sorcery
|
|
25
25
|
:@user_class => nil,
|
26
26
|
:@submodules => [],
|
27
27
|
:@not_authenticated_action => :not_authenticated,
|
28
|
-
:@login_sources =>
|
29
|
-
:@after_login =>
|
30
|
-
:@after_failed_login =>
|
31
|
-
:@before_logout =>
|
32
|
-
:@after_logout =>
|
33
|
-
:@after_remember_me =>
|
28
|
+
:@login_sources => Set.new,
|
29
|
+
:@after_login => Set.new,
|
30
|
+
:@after_failed_login => Set.new,
|
31
|
+
:@before_logout => Set.new,
|
32
|
+
:@after_logout => Set.new,
|
33
|
+
:@after_remember_me => Set.new,
|
34
34
|
:@save_return_to_url => true,
|
35
35
|
:@cookie_domain => nil
|
36
36
|
}
|
@@ -30,9 +30,11 @@ module Sorcery
|
|
30
30
|
end
|
31
31
|
merge_activity_logging_defaults!
|
32
32
|
end
|
33
|
-
|
34
|
-
Config.after_login
|
35
|
-
Config.
|
33
|
+
|
34
|
+
Config.after_login << :register_login_time_to_db
|
35
|
+
Config.after_login << :register_last_ip_address
|
36
|
+
Config.before_logout << :register_logout_time_to_db
|
37
|
+
|
36
38
|
base.after_action :register_last_activity_time_to_db
|
37
39
|
end
|
38
40
|
|
@@ -25,6 +25,9 @@ module Sorcery
|
|
25
25
|
require 'sorcery/providers/microsoft'
|
26
26
|
require 'sorcery/providers/instagram'
|
27
27
|
require 'sorcery/providers/auth0'
|
28
|
+
require 'sorcery/providers/line'
|
29
|
+
require 'sorcery/providers/discord'
|
30
|
+
require 'sorcery/providers/battlenet'
|
28
31
|
|
29
32
|
Config.module_eval do
|
30
33
|
class << self
|
@@ -37,7 +40,7 @@ module Sorcery
|
|
37
40
|
providers.each do |name|
|
38
41
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
39
42
|
def self.#{name}
|
40
|
-
@#{name} ||= Sorcery::Providers.const_get('#{name}'.to_s.
|
43
|
+
@#{name} ||= Sorcery::Providers.const_get('#{name}'.to_s.classify).new
|
41
44
|
end
|
42
45
|
RUBY
|
43
46
|
end
|
@@ -17,6 +17,7 @@ module Sorcery
|
|
17
17
|
end
|
18
18
|
merge_remember_me_defaults!
|
19
19
|
end
|
20
|
+
|
20
21
|
Config.login_sources << :login_from_cookie
|
21
22
|
Config.before_logout << :forget_me!
|
22
23
|
end
|
@@ -54,7 +55,7 @@ module Sorcery
|
|
54
55
|
# and logs the user in if found.
|
55
56
|
# Runs as a login source. See 'current_user' method for how it is used.
|
56
57
|
def login_from_cookie
|
57
|
-
user = cookies.signed[:remember_me_token] && user_class.sorcery_adapter.find_by_remember_me_token(cookies.signed[:remember_me_token])
|
58
|
+
user = cookies.signed[:remember_me_token] && user_class.sorcery_adapter.find_by_remember_me_token(cookies.signed[:remember_me_token]) if defined? cookies
|
58
59
|
if user && user.has_remember_me_token?
|
59
60
|
set_remember_me_cookie!(user)
|
60
61
|
session[:user_id] = user.id.to_s
|
@@ -40,6 +40,10 @@ module Sorcery
|
|
40
40
|
# You are good to go!
|
41
41
|
class BCrypt
|
42
42
|
class << self
|
43
|
+
# Setting the option :pepper allows users to append an app-specific secret token.
|
44
|
+
# Basically it's equivalent to :salt_join_token option, but have a different name to ensure
|
45
|
+
# backward compatibility in generating/matching passwords.
|
46
|
+
attr_accessor :pepper
|
43
47
|
# This is the :cost option for the BCrpyt library.
|
44
48
|
# The higher the cost the more secure it is and the longer is take the generate a hash. By default this is 10.
|
45
49
|
# Set this to whatever you want, play around with it to get that perfect balance between
|
@@ -77,12 +81,13 @@ module Sorcery
|
|
77
81
|
|
78
82
|
def reset!
|
79
83
|
@cost = 10
|
84
|
+
@pepper = ''
|
80
85
|
end
|
81
86
|
|
82
87
|
private
|
83
88
|
|
84
89
|
def join_tokens(tokens)
|
85
|
-
tokens.flatten.join
|
90
|
+
tokens.flatten.join.concat(pepper.to_s) # make sure to add pepper in case tokens have only one element
|
86
91
|
end
|
87
92
|
|
88
93
|
def new_from_hash(hash)
|
data/lib/sorcery/engine.rb
CHANGED
@@ -7,12 +7,18 @@ module Sorcery
|
|
7
7
|
class Engine < Rails::Engine
|
8
8
|
config.sorcery = ::Sorcery::Controller::Config
|
9
9
|
|
10
|
+
# TODO: Should this include a modified version of the helper methods?
|
10
11
|
initializer 'extend Controller with sorcery' do
|
11
|
-
#
|
12
|
+
# FIXME: on_load is needed to fix Rails 6 deprecations, but it breaks
|
13
|
+
# applications due to undefined method errors.
|
14
|
+
# ActiveSupport.on_load(:action_controller_api) do
|
12
15
|
if defined?(ActionController::API)
|
13
16
|
ActionController::API.send(:include, Sorcery::Controller)
|
14
17
|
end
|
15
18
|
|
19
|
+
# FIXME: on_load is needed to fix Rails 6 deprecations, but it breaks
|
20
|
+
# applications due to undefined method errors.
|
21
|
+
# ActiveSupport.on_load(:action_controller_base) do
|
16
22
|
if defined?(ActionController::Base)
|
17
23
|
ActionController::Base.send(:include, Sorcery::Controller)
|
18
24
|
ActionController::Base.helper_method :current_user
|
data/lib/sorcery/model.rb
CHANGED
@@ -102,10 +102,6 @@ module Sorcery
|
|
102
102
|
|
103
103
|
set_encryption_attributes
|
104
104
|
|
105
|
-
unless user.valid_password?(credentials[1])
|
106
|
-
return authentication_response(user: user, failure: :invalid_password, &block)
|
107
|
-
end
|
108
|
-
|
109
105
|
if user.respond_to?(:active_for_authentication?) && !user.active_for_authentication?
|
110
106
|
return authentication_response(user: user, failure: :inactive, &block)
|
111
107
|
end
|
@@ -118,6 +114,10 @@ module Sorcery
|
|
118
114
|
end
|
119
115
|
end
|
120
116
|
|
117
|
+
unless user.valid_password?(credentials[1])
|
118
|
+
return authentication_response(user: user, failure: :invalid_password, &block)
|
119
|
+
end
|
120
|
+
|
121
121
|
authentication_response(user: user, return_value: user, &block)
|
122
122
|
end
|
123
123
|
|
@@ -142,6 +142,7 @@ module Sorcery
|
|
142
142
|
def set_encryption_attributes
|
143
143
|
@sorcery_config.encryption_provider.stretches = @sorcery_config.stretches if @sorcery_config.encryption_provider.respond_to?(:stretches) && @sorcery_config.stretches
|
144
144
|
@sorcery_config.encryption_provider.join_token = @sorcery_config.salt_join_token if @sorcery_config.encryption_provider.respond_to?(:join_token) && @sorcery_config.salt_join_token
|
145
|
+
@sorcery_config.encryption_provider.pepper = @sorcery_config.pepper if @sorcery_config.encryption_provider.respond_to?(:pepper) && @sorcery_config.pepper
|
145
146
|
end
|
146
147
|
|
147
148
|
def add_config_inheritance
|
@@ -205,7 +206,7 @@ module Sorcery
|
|
205
206
|
def generic_send_email(method, mailer)
|
206
207
|
config = sorcery_config
|
207
208
|
mail = config.send(mailer).send(config.send(method), self)
|
208
|
-
return unless
|
209
|
+
return unless mail.respond_to?(config.email_delivery_method)
|
209
210
|
|
210
211
|
mail.send(config.email_delivery_method)
|
211
212
|
end
|
data/lib/sorcery/model/config.rb
CHANGED
@@ -12,7 +12,11 @@ module Sorcery
|
|
12
12
|
attr_accessor :downcase_username_before_authenticating
|
13
13
|
# change default crypted_password attribute.
|
14
14
|
attr_accessor :crypted_password_attribute_name
|
15
|
+
# application-specific secret token that is joined with the password and its salt.
|
16
|
+
# Currently available with BCrypt (default crypt provider) only.
|
17
|
+
attr_accessor :pepper
|
15
18
|
# what pattern to use to join the password with the salt
|
19
|
+
# APPLICABLE TO MD5, SHA1, SHA256, SHA512. Other crypt providers (incl. BCrypt) ignore this parameter.
|
16
20
|
attr_accessor :salt_join_token
|
17
21
|
# change default salt attribute.
|
18
22
|
attr_accessor :salt_attribute_name
|
@@ -57,6 +61,7 @@ module Sorcery
|
|
57
61
|
:@encryption_provider => CryptoProviders::BCrypt,
|
58
62
|
:@custom_encryption_provider => nil,
|
59
63
|
:@encryption_key => nil,
|
64
|
+
:@pepper => '',
|
60
65
|
:@salt_join_token => '',
|
61
66
|
:@salt_attribute_name => :salt,
|
62
67
|
:@stretches => nil,
|
@@ -52,10 +52,13 @@ module Sorcery
|
|
52
52
|
module ClassMethods
|
53
53
|
# Find user by token, also checks for expiration.
|
54
54
|
# Returns the user if token found and is valid.
|
55
|
-
def load_from_magic_login_token(token)
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
def load_from_magic_login_token(token, &block)
|
56
|
+
load_from_token(
|
57
|
+
token,
|
58
|
+
@sorcery_config.magic_login_token_attribute_name,
|
59
|
+
@sorcery_config.magic_login_token_expires_at_attribute_name,
|
60
|
+
&block
|
61
|
+
)
|
59
62
|
end
|
60
63
|
|
61
64
|
protected
|
@@ -124,10 +124,14 @@ module Sorcery
|
|
124
124
|
end
|
125
125
|
|
126
126
|
# Clears token and tries to update the new password for the user.
|
127
|
-
def change_password
|
127
|
+
def change_password(new_password, raise_on_failure: false)
|
128
128
|
clear_reset_password_token
|
129
129
|
send(:"#{sorcery_config.password_attribute_name}=", new_password)
|
130
|
-
sorcery_adapter.save raise_on_failure:
|
130
|
+
sorcery_adapter.save raise_on_failure: raise_on_failure
|
131
|
+
end
|
132
|
+
|
133
|
+
def change_password!(new_password)
|
134
|
+
change_password(new_password, raise_on_failure: true)
|
131
135
|
end
|
132
136
|
|
133
137
|
protected
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Sorcery
|
2
|
+
module Providers
|
3
|
+
# This class adds support for OAuth with BattleNet
|
4
|
+
|
5
|
+
class Battlenet < Base
|
6
|
+
include Protocols::Oauth2
|
7
|
+
|
8
|
+
attr_accessor :auth_path, :scope, :token_url, :user_info_path
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
super
|
12
|
+
|
13
|
+
@scope = 'openid'
|
14
|
+
@site = 'https://eu.battle.net/'
|
15
|
+
@auth_path = '/oauth/authorize'
|
16
|
+
@token_url = '/oauth/token'
|
17
|
+
@user_info_path = '/oauth/userinfo'
|
18
|
+
@state = SecureRandom.hex(16)
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_user_hash(access_token)
|
22
|
+
response = access_token.get(user_info_path)
|
23
|
+
body = JSON.parse(response.body)
|
24
|
+
auth_hash(access_token).tap do |h|
|
25
|
+
h[:user_info] = body
|
26
|
+
h[:battletag] = body['battletag']
|
27
|
+
h[:uid] = body['id']
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# calculates and returns the url to which the user should be redirected,
|
32
|
+
# to get authenticated at the external provider's site.
|
33
|
+
def login_url(_params, _session)
|
34
|
+
authorize_url(authorize_url: auth_path)
|
35
|
+
end
|
36
|
+
|
37
|
+
# tries to login the user from access token
|
38
|
+
def process_callback(params, _session)
|
39
|
+
args = { code: params[:code] }
|
40
|
+
get_access_token(
|
41
|
+
args,
|
42
|
+
token_url: token_url,
|
43
|
+
client_id: @key,
|
44
|
+
client_secret: @secret,
|
45
|
+
grant_type: 'authorization_code',
|
46
|
+
token_method: :post
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|