jwt_keeper 4.0.1 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/jwt_keeper/controller.rb +1 -1
- data/lib/jwt_keeper/token.rb +25 -16
- data/lib/jwt_keeper/version.rb +1 -1
- data/spec/lib/jwt_keeper/controller_spec.rb +1 -0
- data/spec/lib/jwt_keeper/token_spec.rb +32 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0781e4deae7439d13aadad57e1c3fa6dd224cd791c90672ee647815af2ebf70a'
|
4
|
+
data.tar.gz: 9be046da200f6d6f6e17c2f747c398e7b5abe13e1fe1517a7b288d9dec468ea8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a58d6573eb512abce406c8726a15eebac3136d5c05b5305c9b5cd8d040f2facd6c050071d86a8bb885523485ea6217b2596f6bc14771d0e5d0c878278b0bdd66
|
7
|
+
data.tar.gz: 6a1086f9933a1daf4fc48e2ea7af4c2fe8c7b26c248a84f096cde00e9e2af3302258a894cdcb88211a281756a2b847713d6a6bd87233b66d1ca10fe64b3b6459
|
data/lib/jwt_keeper/token.rb
CHANGED
@@ -2,14 +2,16 @@ module JWTKeeper
|
|
2
2
|
# This class acts as the main interface to wrap the concerns of JWTs. Handling everything from
|
3
3
|
# encoding to invalidation.
|
4
4
|
class Token
|
5
|
-
attr_accessor :claims, :cookie_secret
|
5
|
+
attr_accessor :claims, :secret, :cookie_secret
|
6
6
|
|
7
7
|
# Initalizes a new web token
|
8
|
-
# @param
|
9
|
-
# @param
|
8
|
+
# @param options [Hash] the custom claims to encode
|
9
|
+
# @param secret the secret to use during encoding, defaults to config
|
10
|
+
# @param cookie_secret the cookie secret to use during encoding
|
10
11
|
# @return [void]
|
11
|
-
def initialize(
|
12
|
-
@
|
12
|
+
def initialize(options = {})
|
13
|
+
@secret = options.delete(:secret) || JWTKeeper.configuration.secret
|
14
|
+
@cookie_secret = options.delete(:cookie_secret)
|
13
15
|
@claims = {
|
14
16
|
nbf: DateTime.now.to_i, # not before
|
15
17
|
iat: DateTime.now.to_i, # issued at
|
@@ -17,27 +19,28 @@ module JWTKeeper
|
|
17
19
|
}
|
18
20
|
|
19
21
|
@claims.merge!(JWTKeeper.configuration.base_claims)
|
20
|
-
@claims.merge!(
|
22
|
+
@claims.merge!(options)
|
21
23
|
@claims[:exp] = @claims[:exp].to_i if @claims[:exp].is_a?(Time)
|
22
24
|
end
|
23
25
|
|
24
26
|
# Creates a new web token
|
25
|
-
# @param
|
27
|
+
# @param options [Hash] the custom claims to encode
|
28
|
+
# @param secret the secret to use during encoding, defaults to config
|
26
29
|
# @return [Token] token object
|
27
|
-
def self.create(
|
30
|
+
def self.create(options)
|
28
31
|
cookie_secret = SecureRandom.hex(16) if JWTKeeper.configuration.cookie_lock
|
29
|
-
new(
|
32
|
+
new(options.merge(cookie_secret: cookie_secret))
|
30
33
|
end
|
31
34
|
|
32
35
|
# Decodes and validates an existing token
|
33
36
|
# @param raw_token [String] the raw token
|
34
37
|
# @param cookie_secret [String] the cookie secret
|
35
38
|
# @return [Token] token object
|
36
|
-
def self.find(raw_token, cookie_secret
|
37
|
-
claims = decode(raw_token, cookie_secret)
|
39
|
+
def self.find(raw_token, secret: nil, cookie_secret: nil)
|
40
|
+
claims = decode(raw_token, secret: secret, cookie_secret: cookie_secret)
|
38
41
|
return nil if claims.nil?
|
39
42
|
|
40
|
-
new_token = new(
|
43
|
+
new_token = new(secret: secret, cookie_secret: cookie_secret)
|
41
44
|
new_token.claims = claims
|
42
45
|
|
43
46
|
return nil if new_token.revoked?
|
@@ -114,7 +117,11 @@ module JWTKeeper
|
|
114
117
|
# Checks if the token invalid?
|
115
118
|
# @return [Boolean]
|
116
119
|
def invalid?
|
117
|
-
self.class.decode(
|
120
|
+
self.class.decode(
|
121
|
+
encode,
|
122
|
+
secret: secret,
|
123
|
+
cookie_secret: cookie_secret
|
124
|
+
).nil? || revoked?
|
118
125
|
end
|
119
126
|
|
120
127
|
# Encodes the jwt
|
@@ -134,8 +141,10 @@ module JWTKeeper
|
|
134
141
|
end
|
135
142
|
|
136
143
|
# @!visibility private
|
137
|
-
def self.decode(raw_token, cookie_secret)
|
138
|
-
|
144
|
+
def self.decode(raw_token, secret: nil, cookie_secret: nil)
|
145
|
+
secret ||= JWTKeeper.configuration.secret
|
146
|
+
|
147
|
+
JWT.decode(raw_token, secret.to_s + cookie_secret.to_s, true,
|
139
148
|
algorithm: JWTKeeper.configuration.algorithm,
|
140
149
|
verify_iss: true,
|
141
150
|
verify_aud: true,
|
@@ -156,7 +165,7 @@ module JWTKeeper
|
|
156
165
|
# @!visibility private
|
157
166
|
def encode
|
158
167
|
JWT.encode(claims.compact,
|
159
|
-
|
168
|
+
secret.to_s + cookie_secret.to_s,
|
160
169
|
JWTKeeper.configuration.algorithm
|
161
170
|
)
|
162
171
|
end
|
data/lib/jwt_keeper/version.rb
CHANGED
@@ -24,6 +24,15 @@ module JWTKeeper
|
|
24
24
|
it { is_expected.to be_instance_of described_class }
|
25
25
|
it { expect(subject.claims[:exp]).to eql private_claims[:exp] }
|
26
26
|
end
|
27
|
+
|
28
|
+
context 'when overriding default secret' do
|
29
|
+
subject { described_class.create(**private_claims, secret: secret) }
|
30
|
+
|
31
|
+
let(:secret) { SecureRandom.uuid }
|
32
|
+
|
33
|
+
it { is_expected.to be_instance_of described_class }
|
34
|
+
it { expect(subject.claims[:claim]).to eql private_claims[:claim] }
|
35
|
+
end
|
27
36
|
end
|
28
37
|
|
29
38
|
describe '.find' do
|
@@ -46,20 +55,30 @@ module JWTKeeper
|
|
46
55
|
before { JWTKeeper.configure(JWTKeeper::Configuration.new(config.merge(cookie_lock: true))) }
|
47
56
|
|
48
57
|
context 'with no cookie' do
|
49
|
-
subject { described_class.find(raw_token, nil) }
|
58
|
+
subject { described_class.find(raw_token, cookie_secret: nil) }
|
50
59
|
it { is_expected.to be nil }
|
51
60
|
end
|
52
61
|
|
53
62
|
context 'with bad cookie' do
|
54
|
-
subject { described_class.find(raw_token, 'BAD_COOKIE') }
|
63
|
+
subject { described_class.find(raw_token, cookie_secret: 'BAD_COOKIE') }
|
55
64
|
it { is_expected.to be nil }
|
56
65
|
end
|
57
66
|
|
58
67
|
context 'with valid cookie' do
|
59
|
-
subject { described_class.find(raw_token, token.cookie_secret) }
|
68
|
+
subject { described_class.find(raw_token, cookie_secret: token.cookie_secret) }
|
60
69
|
it { is_expected.to be_instance_of described_class }
|
61
70
|
end
|
62
71
|
end
|
72
|
+
|
73
|
+
context 'when overriding default secret' do
|
74
|
+
subject { described_class.find(raw_token, secret: secret) }
|
75
|
+
|
76
|
+
let(:token) { described_class.create(**private_claims, secret: secret) }
|
77
|
+
let(:secret) { SecureRandom.uuid }
|
78
|
+
|
79
|
+
it { is_expected.to be_instance_of described_class }
|
80
|
+
it { expect(subject.claims[:claim]).to eql private_claims[:claim] }
|
81
|
+
end
|
63
82
|
end
|
64
83
|
|
65
84
|
describe '.rotate' do
|
@@ -194,6 +213,16 @@ module JWTKeeper
|
|
194
213
|
context 'when valid' do
|
195
214
|
it { is_expected.to be_valid }
|
196
215
|
end
|
216
|
+
|
217
|
+
context 'with overriden secret' do
|
218
|
+
subject { described_class.create(**private_claims, secret: secret) }
|
219
|
+
|
220
|
+
let(:secret) { SecureRandom.uuid }
|
221
|
+
|
222
|
+
context 'when valid' do
|
223
|
+
it { is_expected.to be_valid }
|
224
|
+
end
|
225
|
+
end
|
197
226
|
end
|
198
227
|
|
199
228
|
describe '#invalid?' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jwt_keeper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Rivera
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2021-02-
|
12
|
+
date: 2021-02-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|