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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8fe59582c2a9d3d581ce7ab57a0356ef6ec9e016649a629b03d28154e4e0b375
4
- data.tar.gz: 0f12ca584291b8570ce2191973542a4e7f114202940c0ed0562968a20362edca
3
+ metadata.gz: 1382a5dd59aa20018fddf7489d73318e5fc217c2c7344e87cd9bea8f61452152
4
+ data.tar.gz: 0165234c70b5b5a411c7eefbb2c59aef0903bbf73bc8c0de611ace157742a341
5
5
  SHA512:
6
- metadata.gz: 26d4ad5a14429700ddab2f37324485543010e7658d18bdfa63dddbc8dff6e1911acf69823584c19b47ec0af4ac6dc043d37b638477fe33f003e957a14fa48f1c
7
- data.tar.gz: 6d4faa18e5abe1ca845d9e4c36fdc2638143c0fc7da65d0c3d04d2570ca31da0477f545aa234d1b54c59378e511076ef40dfad23bfc5f994dc512049ea715c42
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 the app secrets.
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.secrets.secret_jwt_encryption_key
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
@@ -61,7 +61,7 @@ module JWTSessions
61
61
  token_attrs[:access_uid],
62
62
  token_attrs[:access_expiration],
63
63
  store,
64
- namespace: namespace,
64
+ namespace: token_attrs[:namespace] || namespace,
65
65
  payload: {},
66
66
  uid: uid,
67
67
  expiration: token_attrs[:expiration]
@@ -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
- begin
14
- require "redis"
15
- @storage = configure_redis_client(options)
16
- rescue LoadError => e
17
- msg = "Could not load the 'redis' gem, please add it to your gemfile or " \
18
- "configure a different adapter (e.g. JWTSessions.store_adapter = :memory)"
19
- raise e.class, msg, e.backtrace
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.each_with_index.each_with_object({}) { |(key, index), acc| acc[key] = values[index] }
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 = storage.keys(refresh_key("*", 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
- acc[uid] = fetch_refresh(uid, namespace)
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
- (storage.keys(key) || []).first
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JWTSessions
4
- VERSION = "2.5.1"
4
+ VERSION = "2.7.2"
5
5
  end
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.constants - [:Unsupported]
159
- algos.map { |algo| JWT::Algos.const_get(algo)::SUPPORTED }.flatten + [NONE]
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 test_error_on_unknown_option
24
- assert_raises ArgumentError do
25
- JWTSessions::StoreAdapters::RedisStoreAdapter.new(
26
- redis_url: "redis://127.0.0.1:6379/0",
27
- something: "something"
28
- )
29
- end
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.5.1
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: 2020-04-20 00:00:00.000000000 Z
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.1.1
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.1.1
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.0.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: