slots-jwt 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +121 -6
- data/app/controllers/slots/jwt/sessions_controller.rb +38 -0
- data/app/models/slots/jwt/application_record.rb +9 -0
- data/app/models/slots/jwt/session.rb +44 -0
- data/config/initializers/inflections.rb +3 -0
- data/config/routes.rb +2 -2
- data/lib/generators/slots/install/USAGE +1 -1
- data/lib/generators/slots/install/install_generator.rb +1 -1
- data/lib/generators/slots/install/templates/create_slots_sessions.rb +2 -2
- data/lib/generators/slots/install/templates/slots.rb +1 -1
- data/lib/generators/slots/model/model_generator.rb +1 -1
- data/lib/slots.rb +1 -44
- data/lib/slots/jwt.rb +49 -0
- data/lib/slots/jwt/authentication_helper.rb +147 -0
- data/lib/slots/jwt/configuration.rb +84 -0
- data/lib/slots/jwt/database_authentication.rb +21 -0
- data/lib/slots/jwt/engine.rb +9 -0
- data/lib/slots/jwt/extra_classes.rb +14 -0
- data/lib/slots/jwt/generic_methods.rb +53 -0
- data/lib/slots/jwt/generic_validations.rb +53 -0
- data/lib/slots/jwt/permission_filter.rb +37 -0
- data/lib/slots/jwt/slokens.rb +115 -0
- data/lib/slots/jwt/tests.rb +37 -0
- data/lib/slots/jwt/tokens.rb +104 -0
- data/lib/slots/jwt/type_helper.rb +30 -0
- data/lib/slots/{version.rb → jwt/version.rb} +3 -1
- data/lib/tasks/slots_tasks.rake +5 -5
- metadata +23 -19
- data/app/controllers/slots/sessions_controller.rb +0 -36
- data/app/mailers/slots/application_mailer.rb +0 -8
- data/app/models/slots/application_record.rb +0 -7
- data/app/models/slots/session.rb +0 -42
- data/lib/slots/authentication_helper.rb +0 -144
- data/lib/slots/configuration.rb +0 -82
- data/lib/slots/database_authentication.rb +0 -19
- data/lib/slots/engine.rb +0 -7
- data/lib/slots/extra_classes.rb +0 -12
- data/lib/slots/generic_methods.rb +0 -51
- data/lib/slots/generic_validations.rb +0 -51
- data/lib/slots/slokens.rb +0 -113
- data/lib/slots/tests.rb +0 -35
- data/lib/slots/tokens.rb +0 -102
@@ -0,0 +1,147 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slots
|
4
|
+
module JWT
|
5
|
+
module AuthenticationHelper
|
6
|
+
ALL = Object.new
|
7
|
+
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
include ActionController::HttpAuthentication::Token::ControllerMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
def jw_token
|
15
|
+
return @_jw_token if instance_variable_defined?(:@_jw_token)
|
16
|
+
token = authenticate_with_http_token { |t, _| t }
|
17
|
+
@_jw_token = token ? Slots::JWT::Slokens.decode(token) : nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def jw_token!
|
21
|
+
jw_token&.valid!
|
22
|
+
end
|
23
|
+
|
24
|
+
def update_expired_session_tokens
|
25
|
+
return false unless Slots::JWT.configuration.session_lifetime
|
26
|
+
return false unless jw_token&.expired? && jw_token.session.present?
|
27
|
+
new_session_token
|
28
|
+
end
|
29
|
+
|
30
|
+
def new_session_token
|
31
|
+
_current_user = Slots::JWT.configuration.authentication_model.from_sloken(@_jw_token)
|
32
|
+
return false unless _current_user&.update_session
|
33
|
+
@_current_user = _current_user
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def current_user
|
38
|
+
return @_current_user if instance_variable_defined?(:@_current_user)
|
39
|
+
@_current_user = jw_token ? Slots::JWT.configuration.authentication_model.from_sloken(jw_token!) : nil
|
40
|
+
end
|
41
|
+
def load_user
|
42
|
+
current_user&.valid_in_database? && current_user.allowed_new_token?
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_token_header!
|
46
|
+
# check if current user for logout
|
47
|
+
response.set_header('authorization', "Bearer token=#{current_user.token}") if current_user&.new_token?
|
48
|
+
end
|
49
|
+
|
50
|
+
def require_valid_user
|
51
|
+
# Load user will make sure it is in the database and valid in the database
|
52
|
+
raise Slots::JWT::InvalidToken, "User doesnt exist" if @_require_load_user && !load_user
|
53
|
+
access_denied! unless current_user && (@_ignore_callbacks || token_allowed?)
|
54
|
+
end
|
55
|
+
def require_load_user
|
56
|
+
# Use varaible so that if this action is prepended it will still only be called when checking for valid user,
|
57
|
+
# i.e. so its not called before update_expired_session_tokens if set
|
58
|
+
@_require_load_user = true
|
59
|
+
end
|
60
|
+
def ignore_callbacks
|
61
|
+
@_ignore_callbacks = true
|
62
|
+
end
|
63
|
+
|
64
|
+
def access_denied!
|
65
|
+
raise Slots::JWT::AccessDenied
|
66
|
+
end
|
67
|
+
|
68
|
+
def token_allowed?
|
69
|
+
!(self.class._reject_token?(self))
|
70
|
+
end
|
71
|
+
|
72
|
+
def new_token!(session)
|
73
|
+
current_user.create_token(session)
|
74
|
+
set_token_header!
|
75
|
+
end
|
76
|
+
|
77
|
+
def update_token!
|
78
|
+
current_user.update_token
|
79
|
+
end
|
80
|
+
|
81
|
+
module ClassMethods
|
82
|
+
def update_expired_session_tokens!(**options)
|
83
|
+
prepend_before_action :update_expired_session_tokens, **options
|
84
|
+
after_action :set_token_header!, **options
|
85
|
+
end
|
86
|
+
|
87
|
+
def require_login!(load_user: false, **options)
|
88
|
+
before_action :require_load_user, **options if load_user
|
89
|
+
before_action :require_valid_user, **options
|
90
|
+
end
|
91
|
+
|
92
|
+
def require_user_load!(**options)
|
93
|
+
prepend_before_action :require_load_user, **options
|
94
|
+
end
|
95
|
+
|
96
|
+
def skip_callback!(**options)
|
97
|
+
prepend_before_action :ignore_callbacks, **options
|
98
|
+
end
|
99
|
+
|
100
|
+
def ignore_login!(**options)
|
101
|
+
skip_before_action :require_valid_user, **options
|
102
|
+
skip_before_action :require_load_user, **options, raise: false
|
103
|
+
skip_before_action :update_expired_session_tokens, **options, raise: false
|
104
|
+
skip_after_action :set_token_header!, **options, raise: false
|
105
|
+
end
|
106
|
+
|
107
|
+
def catch_invalid_login(response: {errors: {authentication: ['login or password is invalid']}}, status: :unauthorized)
|
108
|
+
rescue_from Slots::JWT::AuthenticationFailed do |exception|
|
109
|
+
render json: response, status: status
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def catch_invalid_token(response: {errors: {authentication: ['invalid or missing token']}}, status: :unauthorized)
|
114
|
+
rescue_from Slots::JWT::InvalidToken do |exception|
|
115
|
+
render json: response, status: status
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def catch_access_denied(response: {errors: {authorization: ["can't access"]}}, status: :forbidden)
|
120
|
+
rescue_from Slots::JWT::AccessDenied do |exception|
|
121
|
+
render json: response, status: status
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def reject_token(only: ALL, except: ALL, &block)
|
126
|
+
raise 'Cant pass both only and except' unless only == ALL || except == ALL
|
127
|
+
only = Array(only) if only != ALL
|
128
|
+
except = Array(except) if except != ALL
|
129
|
+
|
130
|
+
(@_reject_token ||= []).push([only, except, block])
|
131
|
+
end
|
132
|
+
def _reject_token?(con)
|
133
|
+
(@_reject_token ||= []).any? { |o, e, b| _check_to_reject?(con, o, e, b) } || _superclass_reject_token?(con)
|
134
|
+
end
|
135
|
+
def _check_to_reject?(con, only, except, block)
|
136
|
+
return false unless only == ALL || only.any? { |o| o.to_sym == con.action_name.to_sym }
|
137
|
+
return false if except != ALL && except.any? { |e| e.to_sym == con.action_name.to_sym }
|
138
|
+
con.instance_eval(&block)
|
139
|
+
end
|
140
|
+
|
141
|
+
def _superclass_reject_token?(con)
|
142
|
+
self.superclass.respond_to?('_reject_token?') && self.superclass._reject_token?(con)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Slots
|
6
|
+
module JWT
|
7
|
+
class Configuration
|
8
|
+
attr_accessor :login_regex_validations, :token_lifetime, :session_lifetime, :previous_jwt_lifetime
|
9
|
+
attr_reader :logins
|
10
|
+
attr_writer :authentication_model
|
11
|
+
|
12
|
+
# raise_no_error is used for rake to load
|
13
|
+
def initialize
|
14
|
+
@logins = {email: //}
|
15
|
+
@login_regex_validations = true
|
16
|
+
@authentication_model = 'User'
|
17
|
+
@secret_keys = [{created_at: 0, secret: ENV['SLOT_SECRET']}]
|
18
|
+
@token_lifetime = 1.hour
|
19
|
+
@session_lifetime = 2.weeks # Set to nil if you dont want sessions
|
20
|
+
@previous_jwt_lifetime = 5.seconds # Set to nil if you dont want sessions
|
21
|
+
@manage_callbacks = Proc.new { }
|
22
|
+
end
|
23
|
+
|
24
|
+
def logins=(value)
|
25
|
+
if value.is_a? Symbol
|
26
|
+
@logins = {value => //}
|
27
|
+
elsif value.is_a?(Hash)
|
28
|
+
# Should do most inclusive regex last
|
29
|
+
raise 'must be hash of symbols => regex' unless value.length > 0 && value.all? { |k, v| k.is_a?(Symbol) && v.is_a?(Regexp) }
|
30
|
+
@logins = value
|
31
|
+
else
|
32
|
+
raise 'must be a symbol or hash'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def authentication_model
|
37
|
+
@authentication_model.to_s.constantize rescue nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def secret=(v)
|
41
|
+
@secret_keys = [{created_at: 0, secret: v}]
|
42
|
+
end
|
43
|
+
|
44
|
+
def secret_yaml=(file_path_string)
|
45
|
+
secret_keys = YAML.load_file(Slots::JWT.secret_yaml_file)
|
46
|
+
@secret_keys = []
|
47
|
+
secret_keys.each do |secret_key|
|
48
|
+
raise ArgumentError, 'Need CREATED_AT' unless (created_at = secret_key['CREATED_AT']&.to_i)
|
49
|
+
raise ArgumentError, 'Need SECRET' unless (secret = secret_key['SECRET'])
|
50
|
+
previous_created_at = @secret_keys[-1]&.dig(:created_at) || Time.now.to_i
|
51
|
+
|
52
|
+
raise ArgumentError, 'CREATED_AT must be newest to latest' unless previous_created_at > created_at
|
53
|
+
@secret_keys.push(
|
54
|
+
created_at: created_at,
|
55
|
+
secret: secret
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def secret(at = Time.now.to_i)
|
61
|
+
@secret_keys.each do |secret_hash|
|
62
|
+
return secret_hash[:secret] if at > secret_hash[:created_at]
|
63
|
+
end
|
64
|
+
raise InvalidSecret, 'Invalid Secret'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class << self
|
69
|
+
attr_writer :configuration
|
70
|
+
|
71
|
+
def configuration
|
72
|
+
@configuration ||= Configuration.new
|
73
|
+
end
|
74
|
+
|
75
|
+
def configure
|
76
|
+
yield configuration
|
77
|
+
end
|
78
|
+
|
79
|
+
def secret_yaml_file
|
80
|
+
Rails.root.join('config', 'slots_secrets.yml')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slots
|
4
|
+
module JWT
|
5
|
+
module DatabaseAuthentication
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
has_secure_password
|
10
|
+
end
|
11
|
+
|
12
|
+
# TODO allow super
|
13
|
+
def as_json(*)
|
14
|
+
super.except('password_digest')
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slots
|
4
|
+
module JWT
|
5
|
+
class AuthenticationFailed < StandardError
|
6
|
+
end
|
7
|
+
class InvalidToken < StandardError
|
8
|
+
end
|
9
|
+
class AccessDenied < StandardError
|
10
|
+
end
|
11
|
+
class InvalidSecret < StandardError
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slots
|
4
|
+
module JWT
|
5
|
+
module GenericMethods
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
end
|
10
|
+
|
11
|
+
def allowed_new_token?
|
12
|
+
!(self.class._reject_new_token?(self))
|
13
|
+
end
|
14
|
+
|
15
|
+
def run_token_created_callback
|
16
|
+
self.class._token_created_callback(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def authenticate?(password)
|
20
|
+
password.present? && persisted? && respond_to?(:authenticate) && authenticate(password) && allowed_new_token?
|
21
|
+
end
|
22
|
+
|
23
|
+
def authenticate!(password)
|
24
|
+
raise Slots::JWT::AuthenticationFailed unless self.authenticate?(password)
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
module ClassMethods
|
29
|
+
def find_for_authentication(login)
|
30
|
+
Slots::JWT.configuration.logins.each do |k, v|
|
31
|
+
next unless login&.match(v)
|
32
|
+
return find_by(arel_table[k].lower.eq(login.downcase)) || new
|
33
|
+
end
|
34
|
+
new
|
35
|
+
end
|
36
|
+
|
37
|
+
def reject_new_token(&block)
|
38
|
+
(@_reject_new_token ||= []).push(block)
|
39
|
+
end
|
40
|
+
def _reject_new_token?(user)
|
41
|
+
(@_reject_new_token ||= []).any? { |b| user.instance_eval(&b) }
|
42
|
+
end
|
43
|
+
|
44
|
+
def token_created_callback(&block)
|
45
|
+
(@_token_created_callback ||= []).push(block)
|
46
|
+
end
|
47
|
+
def _token_created_callback(user)
|
48
|
+
(@_token_created_callback ||= []).each { |b| user.instance_eval(&b) }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slots
|
4
|
+
module JWT
|
5
|
+
module GenericValidations
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
validate :unique_and_present, :logins_meets_criteria
|
10
|
+
end
|
11
|
+
|
12
|
+
def logins_meets_criteria
|
13
|
+
return if self.errors.any?
|
14
|
+
return unless Slots::JWT.configuration.login_regex_validations
|
15
|
+
logins = Slots::JWT.configuration.logins
|
16
|
+
login_c = logins.keys
|
17
|
+
logins.each do |col, reg|
|
18
|
+
login_c.delete(col) # Login columns left
|
19
|
+
column_match(reg, col)
|
20
|
+
column_dont_match(reg, col, login_c)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def unique_and_present
|
25
|
+
# Use this rather than validates because logins in configure might not be set yet on include
|
26
|
+
Slots::JWT.configuration.logins.each do |column, _|
|
27
|
+
value = self.send(column)
|
28
|
+
next self.errors.add(column, "can't be blank") unless value.present?
|
29
|
+
|
30
|
+
pk_value = self.send(self.class.primary_key)
|
31
|
+
lower_case = self.class.arel_table[column].lower.eq(value.downcase)
|
32
|
+
next unless self.class.where.not(self.class.primary_key => pk_value).where(lower_case).exists?
|
33
|
+
self.errors.add(column, "has already been taken")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def column_match(regex, column)
|
38
|
+
# TODO change error message to use locals? or something configurable
|
39
|
+
self.errors.add(column, "didn't match login criteria") unless self.send(column).match(regex)
|
40
|
+
end
|
41
|
+
|
42
|
+
def column_dont_match(regex, column_not_to_match, columns)
|
43
|
+
columns.each do |c|
|
44
|
+
# Since we check if any errors should be present
|
45
|
+
self.errors.add(c, "matched #{column_not_to_match} login criteria") if self.send(c).match(regex)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module ClassMethods
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slots
|
4
|
+
module JWT
|
5
|
+
class PermissionFilter
|
6
|
+
def initialize(current_user)
|
7
|
+
@current_user = current_user
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(schema_member, ctx)
|
11
|
+
@schema_member = schema_member
|
12
|
+
return true if _dont_check?
|
13
|
+
allowed?
|
14
|
+
end
|
15
|
+
protected
|
16
|
+
attr_reader :schema_member, :current_user
|
17
|
+
|
18
|
+
private
|
19
|
+
def _dont_check?
|
20
|
+
!schema_member.metadata[:has_required_permission]
|
21
|
+
end
|
22
|
+
|
23
|
+
def required_permission
|
24
|
+
schema_member.metadata[:required_permission]
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid_loaded_user
|
28
|
+
return @valid_loaded_user if instance_variable_defined?(:@valid_loaded_user)
|
29
|
+
@valid_loaded_user = current_user&.valid_in_database? && current_user.allowed_new_token?
|
30
|
+
end
|
31
|
+
|
32
|
+
def is_admin
|
33
|
+
valid_loaded_user && current_user.admin
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jwt'
|
4
|
+
module Slots
|
5
|
+
module JWT
|
6
|
+
class Slokens
|
7
|
+
attr_reader :token, :exp, :iat, :extra_payload, :authentication_model_values, :session
|
8
|
+
def initialize(decode: false, encode: false, token: nil, authentication_record: nil, extra_payload: nil, session: nil)
|
9
|
+
if decode
|
10
|
+
@token = token
|
11
|
+
decode()
|
12
|
+
elsif encode
|
13
|
+
@authentication_model_values = authentication_record.as_json
|
14
|
+
@extra_payload = extra_payload.as_json
|
15
|
+
@session = session
|
16
|
+
update_iat
|
17
|
+
update_exp
|
18
|
+
encode()
|
19
|
+
@valid = true
|
20
|
+
else
|
21
|
+
raise 'must encode or decode'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
def self.decode(token)
|
25
|
+
self.new(decode: true, token: token)
|
26
|
+
end
|
27
|
+
def self.encode(authentication_record, session = '', extra_payload)
|
28
|
+
self.new(encode: true, authentication_record: authentication_record, session: session, extra_payload: extra_payload)
|
29
|
+
end
|
30
|
+
|
31
|
+
def expired?
|
32
|
+
@expired
|
33
|
+
end
|
34
|
+
|
35
|
+
def valid?
|
36
|
+
@valid
|
37
|
+
end
|
38
|
+
|
39
|
+
def valid!
|
40
|
+
raise InvalidToken, "Invalid Token" unless valid?
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def update_token_data(authentication_record, extra_payload)
|
45
|
+
@authentication_model_values = authentication_record.as_json
|
46
|
+
@extra_payload = extra_payload.as_json
|
47
|
+
update_iat
|
48
|
+
encode
|
49
|
+
end
|
50
|
+
|
51
|
+
def update_token(authentication_record, extra_payload)
|
52
|
+
update_exp
|
53
|
+
update_token_data(authentication_record, extra_payload)
|
54
|
+
end
|
55
|
+
|
56
|
+
def payload
|
57
|
+
{
|
58
|
+
authentication_model_key => @authentication_model_values,
|
59
|
+
'exp' => @exp,
|
60
|
+
'iat' => @iat,
|
61
|
+
'session' => @session,
|
62
|
+
'extra_payload' => @extra_payload,
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
def authentication_model_key
|
68
|
+
Slots::JWT.configuration.authentication_model.name.underscore
|
69
|
+
end
|
70
|
+
|
71
|
+
def default_expected_keys
|
72
|
+
['exp', 'iat', 'session', authentication_model_key]
|
73
|
+
end
|
74
|
+
def secret
|
75
|
+
Slots::JWT.configuration.secret(@iat)
|
76
|
+
end
|
77
|
+
def update_iat
|
78
|
+
@iat = Time.now.to_i
|
79
|
+
end
|
80
|
+
def update_exp
|
81
|
+
@exp = Slots::JWT.configuration.token_lifetime.from_now.to_i
|
82
|
+
end
|
83
|
+
def encode
|
84
|
+
@token = ::JWT.encode self.payload, secret, 'HS256'
|
85
|
+
@expired = false
|
86
|
+
@valid = true
|
87
|
+
end
|
88
|
+
|
89
|
+
def decode
|
90
|
+
begin
|
91
|
+
set_payload
|
92
|
+
::JWT.decode @token, secret, true, verify_iat: true, algorithm: 'HS256'
|
93
|
+
rescue ::JWT::ExpiredSignature
|
94
|
+
@expired = true
|
95
|
+
rescue ::JWT::InvalidIatError, ::JWT::VerificationError, ::JWT::DecodeError, NoMethodError, JSON::ParserError, Slots::JWT::InvalidSecret
|
96
|
+
@valid = false
|
97
|
+
else
|
98
|
+
@valid = payload.slice(*default_expected_keys).compact.length == default_expected_keys.length
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def set_payload
|
103
|
+
encoded64 = @token.split('.')[1] || ''
|
104
|
+
string_payload = Base64.decode64(encoded64)
|
105
|
+
local_payload = JSON.parse(string_payload)
|
106
|
+
raise JSON::ParserError unless local_payload.is_a?(Hash)
|
107
|
+
@exp = local_payload['exp']&.to_i
|
108
|
+
@iat = local_payload['iat']&.to_i
|
109
|
+
@session = local_payload['session']
|
110
|
+
@authentication_model_values = local_payload[authentication_model_key]
|
111
|
+
@extra_payload = local_payload['extra_payload']
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|