jwt_sessions 2.5.1 → 2.7.2
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 +37 -0
- data/README.md +24 -2
- data/lib/jwt_sessions/refresh_token.rb +1 -1
- data/lib/jwt_sessions/store_adapters/memory_store_adapter.rb +1 -1
- data/lib/jwt_sessions/store_adapters/redis_store_adapter.rb +46 -14
- data/lib/jwt_sessions/store_adapters.rb +1 -1
- data/lib/jwt_sessions/version.rb +1 -1
- data/lib/jwt_sessions.rb +2 -2
- data/test/units/jwt_sessions/store_adapters/test_redis_store_adapter.rb +18 -7
- metadata +8 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1382a5dd59aa20018fddf7489d73318e5fc217c2c7344e87cd9bea8f61452152
|
4
|
+
data.tar.gz: 0165234c70b5b5a411c7eefbb2c59aef0903bbf73bc8c0de611ace157742a341
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 984be7f82567e3aebb090497c7dfbaee8900987fae0682fc89d98d23e5a1acaf07820a7a0133e360139bf007d16c2f4cde6c2e3e5192a25f0b42cec7ca85970a
|
7
|
+
data.tar.gz: 90a250db30b788624210a271c0c4778bd08c43ca71b00684a882dff631bcc6df31c49c5b1492f02ac20f5699cc86903c6e56713aef59cd2dad7016924bb74c19
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,40 @@
|
|
1
|
+
## 2.7.2 (January 24, 2022)
|
2
|
+
|
3
|
+
Bugfixes:
|
4
|
+
|
5
|
+
- 2.7.1 version didn't include the correct patch
|
6
|
+
|
7
|
+
## 2.7.1 (January 22, 2022)
|
8
|
+
|
9
|
+
Bugfixes:
|
10
|
+
|
11
|
+
- Correctly init namespaced refresh tokens when fetching all tokens from Redis
|
12
|
+
|
13
|
+
## 2.7.0 (October 05, 2021)
|
14
|
+
|
15
|
+
Features:
|
16
|
+
|
17
|
+
- added redis_client setting to JWTSessions::StoreAdapters::RedisStoreAdapter
|
18
|
+
|
19
|
+
## 2.6.0 (June 01, 2021)
|
20
|
+
|
21
|
+
Features:
|
22
|
+
|
23
|
+
- added support for all Redis settings
|
24
|
+
|
25
|
+
Support:
|
26
|
+
|
27
|
+
- updated jwt to '>= 2.2.3'
|
28
|
+
- switched to redis scan when looking for keys
|
29
|
+
- removed extra gems from gemspec deps
|
30
|
+
- updated gems in dummy apps
|
31
|
+
|
32
|
+
## 2.5.2 (July 06, 2020)
|
33
|
+
|
34
|
+
Bugfixes:
|
35
|
+
|
36
|
+
- fixed `Using the last argument as keyword parameters is deprecated;` warnings
|
37
|
+
|
1
38
|
## 2.5.1 (April 20, 2020)
|
2
39
|
|
3
40
|
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.
|
@@ -369,6 +369,21 @@ JWTSessions.token_store = :redis, { redis_url: "redis://localhost:6397" }
|
|
369
369
|
|
370
370
|
**NOTE:** if `REDIS_URL` environment variable is set it is used automatically.
|
371
371
|
|
372
|
+
SSL, timeout, reconnect, etc. redis settings are supported:
|
373
|
+
```ruby
|
374
|
+
JWTSessions.token_store = :redis, {
|
375
|
+
read_timeout: 1.5,
|
376
|
+
reconnect_attempts: 10,
|
377
|
+
ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE }
|
378
|
+
}
|
379
|
+
```
|
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
|
+
|
372
387
|
##### JWT signature
|
373
388
|
|
374
389
|
```ruby
|
@@ -592,6 +607,13 @@ session = JWTSessions::Session.new(namespace: "ie-sessions")
|
|
592
607
|
session.flush_namespaced # will flush all sessions which belong to the same namespace
|
593
608
|
```
|
594
609
|
|
610
|
+
Selectively flush one single session inside a namespace by its access token:
|
611
|
+
|
612
|
+
```ruby
|
613
|
+
session = JWTSessions::Session.new(namespace: "ie-sessions", payload: payload)
|
614
|
+
session.flush_by_access_payload # will flush a specific session which belongs to an existing namespace
|
615
|
+
```
|
616
|
+
|
595
617
|
Flush access tokens only:
|
596
618
|
|
597
619
|
```ruby
|
@@ -5,7 +5,7 @@ module JWTSessions
|
|
5
5
|
class MemoryStoreAdapter < AbstractStoreAdapter
|
6
6
|
attr_reader :storage
|
7
7
|
|
8
|
-
def initialize(options)
|
8
|
+
def initialize(**options)
|
9
9
|
raise ArgumentError, "Memory store doesn't support any options" if options.any?
|
10
10
|
@storage = Hash.new do |h, k|
|
11
11
|
h[k] = Hash.new { |hh, kk| hh[kk] = {} }
|
@@ -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)
|
@@ -62,10 +69,13 @@ module JWTSessions
|
|
62
69
|
end
|
63
70
|
|
64
71
|
def all_refresh_tokens(namespace)
|
65
|
-
keys_in_namespace =
|
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
|
|
@@ -80,7 +90,7 @@ module JWTSessions
|
|
80
90
|
|
81
91
|
private
|
82
92
|
|
83
|
-
def configure_redis_client(redis_url: nil, redis_host: nil, redis_port: nil, redis_db_name: nil)
|
93
|
+
def configure_redis_client(redis_url: nil, redis_host: nil, redis_port: nil, redis_db_name: nil, **options)
|
84
94
|
if redis_url && (redis_host || redis_port || redis_db_name)
|
85
95
|
raise ArgumentError, "redis_url cannot be passed along with redis_host, redis_port or redis_db_name options"
|
86
96
|
end
|
@@ -91,7 +101,7 @@ module JWTSessions
|
|
91
101
|
redis_db_name: redis_db_name
|
92
102
|
)
|
93
103
|
|
94
|
-
Redis.new(url: redis_url)
|
104
|
+
Redis.new(options.merge(url: redis_url))
|
95
105
|
end
|
96
106
|
|
97
107
|
def build_redis_url(redis_host: nil, redis_port: nil, redis_db_name: nil)
|
@@ -111,7 +121,7 @@ module JWTSessions
|
|
111
121
|
|
112
122
|
def first_refresh_key(uid)
|
113
123
|
key = full_refresh_key(uid, "*")
|
114
|
-
(
|
124
|
+
(scan_keys(key) || []).first
|
115
125
|
end
|
116
126
|
|
117
127
|
def refresh_key(uid, namespace)
|
@@ -126,6 +136,28 @@ module JWTSessions
|
|
126
136
|
def uid_from_key(key)
|
127
137
|
key.split("_").last
|
128
138
|
end
|
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
|
+
|
148
|
+
def scan_keys(key_pattern)
|
149
|
+
cursor = 0
|
150
|
+
all_keys = []
|
151
|
+
|
152
|
+
loop do
|
153
|
+
cursor, keys = storage.scan(cursor, match: key_pattern, count: 1000)
|
154
|
+
all_keys |= keys
|
155
|
+
|
156
|
+
break if cursor == "0"
|
157
|
+
end
|
158
|
+
|
159
|
+
all_keys
|
160
|
+
end
|
129
161
|
end
|
130
162
|
end
|
131
163
|
end
|
@@ -9,7 +9,7 @@ module JWTSessions
|
|
9
9
|
def self.build_by_name(adapter, options = nil)
|
10
10
|
camelized_adapter = adapter.to_s.split('_').map(&:capitalize).join
|
11
11
|
adapter_class_name = "#{camelized_adapter}StoreAdapter"
|
12
|
-
StoreAdapters.const_get(adapter_class_name).new(options || {})
|
12
|
+
StoreAdapters.const_get(adapter_class_name).new(**(options || {}))
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
data/lib/jwt_sessions/version.rb
CHANGED
data/lib/jwt_sessions.rb
CHANGED
@@ -155,7 +155,7 @@ module JWTSessions
|
|
155
155
|
private
|
156
156
|
|
157
157
|
def supported_algos
|
158
|
-
algos = JWT::Algos
|
159
|
-
algos.map { |algo|
|
158
|
+
algos = JWT::Algos::ALGOS - [JWT::Algos::Unsupported]
|
159
|
+
algos.map { |algo| algo::SUPPORTED }.flatten + [NONE]
|
160
160
|
end
|
161
161
|
end
|
@@ -20,13 +20,18 @@ class TestRedisStoreAdapter < Minitest::Test
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
def test_support_of_extra_options
|
24
|
+
adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new(
|
25
|
+
redis_url: "redis://127.0.0.1:6379",
|
26
|
+
ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE },
|
27
|
+
reconnect_delay: 2,
|
28
|
+
timeout: 8
|
29
|
+
)
|
30
|
+
options = adapter.storage.instance_variable_get(:@options)
|
31
|
+
|
32
|
+
assert_equal 8, options[:timeout]
|
33
|
+
assert_equal 2, options[:reconnect_delay]
|
34
|
+
assert_equal 0, options[:ssl_params][:verify_mode]
|
30
35
|
end
|
31
36
|
|
32
37
|
def test_default_url
|
@@ -72,4 +77,10 @@ class TestRedisStoreAdapter < Minitest::Test
|
|
72
77
|
adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
|
73
78
|
assert_equal "redis://127.0.0.2:6322/0", adapter.storage.connection[:id]
|
74
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
|
75
86
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yulia Oletskaya
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jwt
|
@@ -16,7 +16,7 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.
|
19
|
+
version: 2.2.3
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: '3'
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 2.
|
29
|
+
version: 2.2.3
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '3'
|
@@ -44,34 +44,6 @@ dependencies:
|
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '1.16'
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: minitest
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - "~>"
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '5.11'
|
54
|
-
type: :development
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
requirements:
|
58
|
-
- - "~>"
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: '5.11'
|
61
|
-
- !ruby/object:Gem::Dependency
|
62
|
-
name: pry
|
63
|
-
requirement: !ruby/object:Gem::Requirement
|
64
|
-
requirements:
|
65
|
-
- - "~>"
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: '0.11'
|
68
|
-
type: :development
|
69
|
-
prerelease: false
|
70
|
-
version_requirements: !ruby/object:Gem::Requirement
|
71
|
-
requirements:
|
72
|
-
- - "~>"
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
version: '0.11'
|
75
47
|
- !ruby/object:Gem::Dependency
|
76
48
|
name: rake
|
77
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,7 +98,7 @@ metadata:
|
|
126
98
|
changelog_uri: https://github.com/tuwukee/jwt_sessions/blob/master/CHANGELOG.md
|
127
99
|
source_code_uri: https://github.com/tuwukee/jwt_sessions
|
128
100
|
bug_tracker_uri: https://github.com/tuwukee/jwt_sessions/issues
|
129
|
-
post_install_message:
|
101
|
+
post_install_message:
|
130
102
|
rdoc_options: []
|
131
103
|
require_paths:
|
132
104
|
- lib
|
@@ -141,8 +113,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
113
|
- !ruby/object:Gem::Version
|
142
114
|
version: '0'
|
143
115
|
requirements: []
|
144
|
-
rubygems_version: 3.
|
145
|
-
signing_key:
|
116
|
+
rubygems_version: 3.2.5
|
117
|
+
signing_key:
|
146
118
|
specification_version: 4
|
147
119
|
summary: JWT Sessions
|
148
120
|
test_files:
|