jwt_sessions 2.6.0 → 2.7.3
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/CHANGELOG.md +28 -0
- data/README.md +8 -2
- data/lib/jwt_sessions/refresh_token.rb +1 -1
- data/lib/jwt_sessions/store_adapters/redis_store_adapter.rb +28 -10
- data/lib/jwt_sessions/token.rb +1 -1
- data/lib/jwt_sessions/version.rb +1 -1
- data/lib/jwt_sessions.rb +1 -3
- data/test/units/jwt_sessions/store_adapters/test_redis_store_adapter.rb +6 -0
- data/test/units/jwt_sessions/test_token.rb +5 -5
- metadata +21 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed69732617f15f4c07c0fb37d3ad938807224b729f136d24755a90f58b7b28ab
|
4
|
+
data.tar.gz: 27bee3f1c2bd4b099b0dadea703143d70e6abf1aaa6e5556f67515dfbc6f2e5b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0a81d8d8013a1393b441ddd15ec34fb57ceb0bd3198f9ee4a2554dff653efbe4379ad6992d1a8678895e0391f45626068a2f16b422ad8c658b7a086a08241d3
|
7
|
+
data.tar.gz: 46e744a4512da3d90b54f6552c42f35c7b3b3d25a9d73292058ac5782102ed9d9c77ac6a734a865b40e2fcccd675257cc5c41d27be45bd5fde758e8d6c97537f
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,31 @@
|
|
1
|
+
## 2.7.3 (August 26, 2022)
|
2
|
+
|
3
|
+
Bugfixes:
|
4
|
+
|
5
|
+
- compatibility with jwt 2.5
|
6
|
+
|
7
|
+
Support:
|
8
|
+
|
9
|
+
- add rspec to development deps
|
10
|
+
|
11
|
+
## 2.7.2 (January 24, 2022)
|
12
|
+
|
13
|
+
Bugfixes:
|
14
|
+
|
15
|
+
- 2.7.1 version didn't include the correct patch
|
16
|
+
|
17
|
+
## 2.7.1 (January 22, 2022)
|
18
|
+
|
19
|
+
Bugfixes:
|
20
|
+
|
21
|
+
- Correctly init namespaced refresh tokens when fetching all tokens from Redis
|
22
|
+
|
23
|
+
## 2.7.0 (October 05, 2021)
|
24
|
+
|
25
|
+
Features:
|
26
|
+
|
27
|
+
- added redis_client setting to JWTSessions::StoreAdapters::RedisStoreAdapter
|
28
|
+
|
1
29
|
## 2.6.0 (June 01, 2021)
|
2
30
|
|
3
31
|
Features:
|
data/README.md
CHANGED
@@ -153,11 +153,11 @@ end
|
|
153
153
|
```
|
154
154
|
|
155
155
|
Specify an encryption key for JSON Web Tokens in `config/initializers/jwt_session.rb` \
|
156
|
-
It is advisable to store the key itself within
|
156
|
+
It is advisable to store the key itself in a secure way, f.e. within app credentials.
|
157
157
|
|
158
158
|
```ruby
|
159
159
|
JWTSessions.algorithm = "HS256"
|
160
|
-
JWTSessions.encryption_key = Rails.application.
|
160
|
+
JWTSessions.encryption_key = Rails.application.credentials.secret_jwt_encryption_key
|
161
161
|
```
|
162
162
|
|
163
163
|
Most of the encryption algorithms require private and public keys to sign a token. However, HMAC requires only a single key and you can use the `encryption_key` shortcut to sign the token. For other algorithms you must specify private and public keys separately.
|
@@ -378,6 +378,12 @@ JWTSessions.token_store = :redis, {
|
|
378
378
|
}
|
379
379
|
```
|
380
380
|
|
381
|
+
If you already have a configured Redis client, you can pass it among the options to reduce opened connections to a Redis server:
|
382
|
+
|
383
|
+
```ruby
|
384
|
+
JWTSessions.token_store = :redis, {redis_client: Redis.current}
|
385
|
+
```
|
386
|
+
|
381
387
|
##### JWT signature
|
382
388
|
|
383
389
|
```ruby
|
@@ -7,16 +7,20 @@ module JWTSessions
|
|
7
7
|
|
8
8
|
REFRESH_KEYS = %i[csrf access_uid access_expiration expiration].freeze
|
9
9
|
|
10
|
-
def initialize(token_prefix: JWTSessions.token_prefix, **options)
|
10
|
+
def initialize(token_prefix: JWTSessions.token_prefix, redis_client: nil, **options)
|
11
11
|
@prefix = token_prefix
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
if redis_client
|
14
|
+
@storage = redis_client
|
15
|
+
else
|
16
|
+
begin
|
17
|
+
require "redis"
|
18
|
+
@storage = configure_redis_client(**options)
|
19
|
+
rescue LoadError => e
|
20
|
+
msg = "Could not load the 'redis' gem, please add it to your gemfile or " \
|
21
|
+
"configure a different adapter (e.g. JWTSessions.store_adapter = :memory)"
|
22
|
+
raise e.class, msg, e.backtrace
|
23
|
+
end
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
@@ -36,7 +40,10 @@ module JWTSessions
|
|
36
40
|
values = storage.hmget(key, *REFRESH_KEYS).compact
|
37
41
|
|
38
42
|
return {} if values.length != REFRESH_KEYS.length
|
39
|
-
REFRESH_KEYS
|
43
|
+
REFRESH_KEYS
|
44
|
+
.each_with_index
|
45
|
+
.each_with_object({}) { |(key, index), acc| acc[key] = values[index] }
|
46
|
+
.merge({ namespace: namespace })
|
40
47
|
end
|
41
48
|
|
42
49
|
def persist_refresh(uid:, access_expiration:, access_uid:, csrf:, expiration:, namespace: nil)
|
@@ -65,7 +72,10 @@ module JWTSessions
|
|
65
72
|
keys_in_namespace = scan_keys(refresh_key("*", namespace))
|
66
73
|
(keys_in_namespace || []).each_with_object({}) do |key, acc|
|
67
74
|
uid = uid_from_key(key)
|
68
|
-
|
75
|
+
# to be able to properly initialize namespaced tokens extract their namespaces
|
76
|
+
# and pass down to fetch_refresh
|
77
|
+
token_namespace = namespace.to_s.empty? ? namespace_from_key(key) : namespace
|
78
|
+
acc[uid] = fetch_refresh(uid, token_namespace)
|
69
79
|
end
|
70
80
|
end
|
71
81
|
|
@@ -127,6 +137,14 @@ module JWTSessions
|
|
127
137
|
key.split("_").last
|
128
138
|
end
|
129
139
|
|
140
|
+
def namespace_from_key(key)
|
141
|
+
ns_regexp.match(key)&.[](:namespace)
|
142
|
+
end
|
143
|
+
|
144
|
+
def ns_regexp
|
145
|
+
@ns_regexp ||= Regexp.new("#{prefix}_(?<namespace>.+)_refresh")
|
146
|
+
end
|
147
|
+
|
130
148
|
def scan_keys(key_pattern)
|
131
149
|
cursor = 0
|
132
150
|
all_keys = []
|
data/lib/jwt_sessions/token.rb
CHANGED
@@ -13,7 +13,7 @@ module JWTSessions
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def decode(token, claims = {})
|
16
|
-
decode_options = { algorithm: JWTSessions.algorithm }.merge(JWTSessions.jwt_options
|
16
|
+
decode_options = { algorithm: JWTSessions.algorithm }.merge(JWTSessions.jwt_options).merge(claims)
|
17
17
|
JWT.decode(token, JWTSessions.public_key, JWTSessions.validate?, decode_options)
|
18
18
|
rescue JWT::ExpiredSignature => e
|
19
19
|
raise Errors::Expired, e.message
|
data/lib/jwt_sessions/version.rb
CHANGED
data/lib/jwt_sessions.rb
CHANGED
@@ -21,8 +21,6 @@ module JWTSessions
|
|
21
21
|
|
22
22
|
NONE = "none"
|
23
23
|
|
24
|
-
JWTOptions = Struct.new(*JWT::DefaultOptions::DEFAULT_OPTIONS.keys)
|
25
|
-
|
26
24
|
DEFAULT_SETTINGS_KEYS = %i[access_cookie
|
27
25
|
access_exp_time
|
28
26
|
access_header
|
@@ -66,7 +64,7 @@ module JWTSessions
|
|
66
64
|
end
|
67
65
|
|
68
66
|
def jwt_options
|
69
|
-
@jwt_options ||=
|
67
|
+
@jwt_options ||= JWT::Configuration::Container.new.decode.to_h
|
70
68
|
end
|
71
69
|
|
72
70
|
def algorithm=(algo)
|
@@ -77,4 +77,10 @@ class TestRedisStoreAdapter < Minitest::Test
|
|
77
77
|
adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
|
78
78
|
assert_equal "redis://127.0.0.2:6322/0", adapter.storage.connection[:id]
|
79
79
|
end
|
80
|
+
|
81
|
+
def test_configuration_via_redis_client
|
82
|
+
client = Object.new
|
83
|
+
adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new(redis_client: client)
|
84
|
+
assert_equal client, adapter.storage
|
85
|
+
end
|
80
86
|
end
|
@@ -24,7 +24,7 @@ class TestToken < Minitest::Test
|
|
24
24
|
|
25
25
|
def teardown
|
26
26
|
JWTSessions.algorithm = JWTSessions::DEFAULT_ALGORITHM
|
27
|
-
JWTSessions.instance_variable_set(:"@jwt_options",
|
27
|
+
JWTSessions.instance_variable_set(:"@jwt_options", JWT::Configuration::Container.new.decode.to_h)
|
28
28
|
end
|
29
29
|
|
30
30
|
def test_rsa_token_decode
|
@@ -73,7 +73,7 @@ class TestToken < Minitest::Test
|
|
73
73
|
|
74
74
|
def test_token_sub_claim
|
75
75
|
JWTSessions.encryption_key = "abcdefghijklmnopqrstuvwxyzABCDEF"
|
76
|
-
JWTSessions.jwt_options
|
76
|
+
JWTSessions.jwt_options[:verify_sub] = true
|
77
77
|
token = JWTSessions::Token.encode(payload.merge(sub: "subject"))
|
78
78
|
decoded = JWTSessions::Token.decode(token, { sub: "subject" }).first
|
79
79
|
assert_equal payload["user_id"], decoded["user_id"]
|
@@ -85,7 +85,7 @@ class TestToken < Minitest::Test
|
|
85
85
|
|
86
86
|
def test_token_iss_claim
|
87
87
|
JWTSessions.encryption_key = "abcdefghijklmnopqrstuvwxyzABCDEF"
|
88
|
-
JWTSessions.jwt_options
|
88
|
+
JWTSessions.jwt_options[:verify_iss] = true
|
89
89
|
token = JWTSessions::Token.encode(payload.merge(iss: "Me"))
|
90
90
|
decoded = JWTSessions::Token.decode(token, { iss: "Me" }).first
|
91
91
|
assert_equal payload["user_id"], decoded["user_id"]
|
@@ -97,7 +97,7 @@ class TestToken < Minitest::Test
|
|
97
97
|
|
98
98
|
def test_token_aud_claim
|
99
99
|
JWTSessions.encryption_key = "abcdefghijklmnopqrstuvwxyzABCDEF"
|
100
|
-
JWTSessions.jwt_options
|
100
|
+
JWTSessions.jwt_options[:verify_aud] = true
|
101
101
|
token = JWTSessions::Token.encode(payload.merge(aud: ["young", "old"]))
|
102
102
|
decoded = JWTSessions::Token.decode(token, { aud: ["young"] }).first
|
103
103
|
assert_equal payload["user_id"], decoded["user_id"]
|
@@ -109,7 +109,7 @@ class TestToken < Minitest::Test
|
|
109
109
|
|
110
110
|
def test_token_leeway_decode
|
111
111
|
JWTSessions.encryption_key = "abcdefghijklmnopqrstuvwxyzABCDEF"
|
112
|
-
JWTSessions.jwt_options
|
112
|
+
JWTSessions.jwt_options[:leeway] = 50
|
113
113
|
token = JWTSessions::Token.encode(payload.merge("exp" => Time.now.to_i - 20))
|
114
114
|
decoded = JWTSessions::Token.decode(token).first
|
115
115
|
assert_equal payload["user_id"], decoded["user_id"]
|
metadata
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jwt_sessions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.7.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yulia Oletskaya
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-08-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jwt
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.
|
19
|
+
version: '2.5'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: '3'
|
@@ -24,9 +24,9 @@ dependencies:
|
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- - "
|
27
|
+
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 2.
|
29
|
+
version: '2.5'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '3'
|
@@ -58,6 +58,20 @@ dependencies:
|
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '12.3'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rspec
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.11'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '3.11'
|
61
75
|
description: XSS/CSRF safe JWT auth designed for SPA
|
62
76
|
email: yulia.oletskaya@gmail.com
|
63
77
|
executables: []
|
@@ -113,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
127
|
- !ruby/object:Gem::Version
|
114
128
|
version: '0'
|
115
129
|
requirements: []
|
116
|
-
rubygems_version: 3.0.3
|
130
|
+
rubygems_version: 3.0.3.1
|
117
131
|
signing_key:
|
118
132
|
specification_version: 4
|
119
133
|
summary: JWT Sessions
|