jwt_sessions 2.7.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed69732617f15f4c07c0fb37d3ad938807224b729f136d24755a90f58b7b28ab
4
- data.tar.gz: 27bee3f1c2bd4b099b0dadea703143d70e6abf1aaa6e5556f67515dfbc6f2e5b
3
+ metadata.gz: 7e7a3aefe57092b27b60f6ef28e6a2acb55f6a18228984b2ca4b08c3e7b887e7
4
+ data.tar.gz: 75eda3e6ec9a47dae19f03a00c0b3e30a99f0f4548b37aae6815aa9e808126d9
5
5
  SHA512:
6
- metadata.gz: a0a81d8d8013a1393b441ddd15ec34fb57ceb0bd3198f9ee4a2554dff653efbe4379ad6992d1a8678895e0391f45626068a2f16b422ad8c658b7a086a08241d3
7
- data.tar.gz: 46e744a4512da3d90b54f6552c42f35c7b3b3d25a9d73292058ac5782102ed9d9c77ac6a734a865b40e2fcccd675257cc5c41d27be45bd5fde758e8d6c97537f
6
+ metadata.gz: 8d2eb29176309d00726b1e7df7d7ace1f914c62c9998b2655f754d9c4992d75bd5db3d54183034c80be889fd43216bc1b548ccbcf52104eea216621923dc6d8e
7
+ data.tar.gz: 5c7ba9621534b445373b2b588b4be2076c2ed7e4266852aea1d653b51f166c85bec1f6de33b9a6445de049e081cb93356d5e92980887849d209a03e39d1b54d9
data/CHANGELOG.md CHANGED
@@ -1,11 +1,25 @@
1
- ## 2.7.3 (August 26, 2022)
1
+ ## 3.0.0 (December 27, 2022)
2
2
 
3
- Bugfixes:
3
+ Features:
4
4
 
5
- - compatibility with jwt 2.5
5
+ - replace `redis` with `redis-client`
6
+ - add `pool_size` setting to support concurrency within `redis-client`'s connection pool
7
+
8
+ Support:
9
+
10
+ - upgrade `jwt` to 2.6 in dependencies
11
+
12
+ ## 2.7.4 (August 31, 2022)
6
13
 
7
14
  Support:
8
15
 
16
+ - compatibility with redis 5.0
17
+
18
+ ## 2.7.3 (August 26, 2022)
19
+
20
+ Support:
21
+
22
+ - compatibility with jwt 2.5
9
23
  - add rspec to development deps
10
24
 
11
25
  ## 2.7.2 (January 24, 2022)
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # jwt_sessions
2
2
  [![Gem Version](https://badge.fury.io/rb/jwt_sessions.svg)](https://badge.fury.io/rb/jwt_sessions)
3
3
  [![Maintainability](https://api.codeclimate.com/v1/badges/53de11b8334933b1c0ef/maintainability)](https://codeclimate.com/github/tuwukee/jwt_sessions/maintainability)
4
- [![Codacy Badge](https://api.codacy.com/project/badge/Grade/c86efdfca81448919ec3e1c1e48fc152)](https://www.codacy.com/app/tuwukee/jwt_sessions?utm_source=github.com&utm_medium=referral&utm_content=tuwukee/jwt_sessions&utm_campaign=Badge_Grade)
4
+ [![Codacy Badge](https://app.codacy.com/project/badge/Grade/6ba02043e42144a9af96c9675207a5c4)](https://www.codacy.com/gh/tuwukee/jwt_sessions/dashboard?utm_source=github.com&utm_medium=referral&utm_content=tuwukee/jwt_sessions&utm_campaign=Badge_Grade)
5
5
  [![Build Status](https://travis-ci.org/tuwukee/jwt_sessions.svg?branch=master)](https://travis-ci.org/tuwukee/jwt_sessions)
6
6
 
7
7
  XSS/CSRF safe JWT auth designed for SPA
@@ -348,7 +348,7 @@ List of configurable settings with their default values.
348
348
 
349
349
  ##### Token store
350
350
 
351
- In order to configure a token store you should set up a store adapter in a following way: `JWTSessions.token_store = :redis, { redis_url: 'redis://127.0.0.1:6379/0' }` (options can be omitted). Currently supported stores are `:redis` and `:memory`. Please note, that if you want to use Redis as a store then you should have `redis` gem listed in your Gemfile. If you do not configure the adapter explicitly, this gem will try to load `redis` and use it. Otherwise it will fall back to a `memory` adapter.
351
+ In order to configure a token store you should set up a store adapter in a following way: `JWTSessions.token_store = :redis, { redis_url: 'redis://127.0.0.1:6379/0' }` (options can be omitted). Currently supported stores are `:redis` and `:memory`. Please note, that if you want to use Redis as a store then you should have `redis-client` gem listed in your Gemfile. If you do not configure the adapter explicitly, this gem will try to load `redis-client` and use it. Otherwise it will fall back to a `memory` adapter.
352
352
 
353
353
  Memory store only accepts a `prefix` (used for Redis db keys). Here is a default configuration for Redis:
354
354
 
@@ -357,9 +357,11 @@ JWTSessions.token_store = :redis, {
357
357
  redis_host: "127.0.0.1",
358
358
  redis_port: "6379",
359
359
  redis_db_name: "0",
360
- token_prefix: "jwt_"
360
+ token_prefix: "jwt_",
361
+ pool_size: Integer(ENV.fetch("RAILS_MAX_THREADS", 5))
361
362
  }
362
363
  ```
364
+ On default `pool_size` is set to 5. Override it with the value of max number of parallel redis connections in your app.
363
365
 
364
366
  You can also provide a Redis URL instead:
365
367
 
@@ -381,7 +383,7 @@ JWTSessions.token_store = :redis, {
381
383
  If you already have a configured Redis client, you can pass it among the options to reduce opened connections to a Redis server:
382
384
 
383
385
  ```ruby
384
- JWTSessions.token_store = :redis, {redis_client: Redis.current}
386
+ JWTSessions.token_store = :redis, {redis_client: redis_pool}
385
387
  ```
386
388
 
387
389
  ##### JWT signature
@@ -409,11 +411,11 @@ jwt_sessions only uses `exp` claim by default when it decodes tokens and you can
409
411
  setting `jwt_options`. You can also specify leeway to account for clock skew.
410
412
 
411
413
  ```ruby
412
- JWTSessions.jwt_options.verify_iss = true
413
- JWTSessions.jwt_options.verify_sub = true
414
- JWTSessions.jwt_options.verify_iat = true
415
- JWTSessions.jwt_options.verify_aud = true
416
- JWTSessions.jwt_options.leeway = 30 # seconds
414
+ JWTSessions.jwt_options[:verify_iss] = true
415
+ JWTSessions.jwt_options[:verify_sub] = true
416
+ JWTSessions.jwt_options[:verify_iat] = true
417
+ JWTSessions.jwt_options[:verify_aud] = true
418
+ JWTSessions.jwt_options[:leeway] = 30 # seconds
417
419
  ```
418
420
 
419
421
  To pass options like `sub`, `aud`, `iss`, or leeways you should specify a method called `token_claims` in your controller.
@@ -89,7 +89,7 @@ module JWTSessions
89
89
  tokens.each do |token|
90
90
  AccessToken.destroy(token.access_uid, store)
91
91
  # unlink refresh token from the current access token
92
- token.update(nil, nil, token.csrf)
92
+ token.update(0, 0, token.csrf)
93
93
  end.count
94
94
  end
95
95
 
@@ -208,7 +208,7 @@ module JWTSessions
208
208
  def check_access_uid_within_refresh_token
209
209
  uid = retrieve_val_from(payload, :access, "uid", "access uid")
210
210
  access_uid = @_refresh.access_uid
211
- return if access_uid.size.zero?
211
+ return if access_uid == "0"
212
212
  yield @_refresh.uid, @_refresh.access_expiration if access_uid != uid
213
213
  end
214
214
 
@@ -6,6 +6,7 @@ module JWTSessions
6
6
  attr_reader :prefix, :storage
7
7
 
8
8
  REFRESH_KEYS = %i[csrf access_uid access_expiration expiration].freeze
9
+ DEFAULT_POOL_SIZE = 5
9
10
 
10
11
  def initialize(token_prefix: JWTSessions.token_prefix, redis_client: nil, **options)
11
12
  @prefix = token_prefix
@@ -14,10 +15,10 @@ module JWTSessions
14
15
  @storage = redis_client
15
16
  else
16
17
  begin
17
- require "redis"
18
+ require "redis-client"
18
19
  @storage = configure_redis_client(**options)
19
20
  rescue LoadError => e
20
- msg = "Could not load the 'redis' gem, please add it to your gemfile or " \
21
+ msg = "Could not load the 'redis-client' gem, please add it to your gemfile or " \
21
22
  "configure a different adapter (e.g. JWTSessions.store_adapter = :memory)"
22
23
  raise e.class, msg, e.backtrace
23
24
  end
@@ -25,21 +26,22 @@ module JWTSessions
25
26
  end
26
27
 
27
28
  def fetch_access(uid)
28
- csrf = storage.get(access_key(uid))
29
+ csrf = storage.call("GET", access_key(uid))
29
30
  csrf.nil? ? {} : { csrf: csrf }
30
31
  end
31
32
 
32
33
  def persist_access(uid, csrf, expiration)
33
34
  key = access_key(uid)
34
- storage.set(key, csrf)
35
- storage.expireat(key, expiration)
35
+ storage.call("SET", key, csrf, ex: expiration)
36
36
  end
37
37
 
38
38
  def fetch_refresh(uid, namespace, first_match = false)
39
39
  key = first_match ? first_refresh_key(uid) : full_refresh_key(uid, namespace)
40
- values = storage.hmget(key, *REFRESH_KEYS).compact
40
+ return {} if key.nil?
41
41
 
42
+ values = storage.call("HMGET", key, *REFRESH_KEYS).compact
42
43
  return {} if values.length != REFRESH_KEYS.length
44
+
43
45
  REFRESH_KEYS
44
46
  .each_with_index
45
47
  .each_with_object({}) { |(key, index), acc| acc[key] = values[index] }
@@ -55,12 +57,12 @@ module JWTSessions
55
57
  csrf: csrf,
56
58
  namespace: namespace
57
59
  )
58
- storage.hset(key, :expiration, expiration)
59
- storage.expireat(key, expiration)
60
+ storage.call("HSET", key, :expiration, expiration)
61
+ storage.call("EXPIREAT", key, expiration)
60
62
  end
61
63
 
62
64
  def update_refresh(uid:, access_expiration:, access_uid:, csrf:, namespace: nil)
63
- storage.hmset(
65
+ storage.call("HMSET",
64
66
  full_refresh_key(uid, namespace),
65
67
  :csrf, csrf,
66
68
  :access_expiration, access_expiration,
@@ -81,11 +83,11 @@ module JWTSessions
81
83
 
82
84
  def destroy_refresh(uid, namespace)
83
85
  key = full_refresh_key(uid, namespace)
84
- storage.del(key)
86
+ storage.call("DEL", key)
85
87
  end
86
88
 
87
89
  def destroy_access(uid)
88
- storage.del(access_key(uid))
90
+ storage.call("DEL", access_key(uid))
89
91
  end
90
92
 
91
93
  private
@@ -100,8 +102,10 @@ module JWTSessions
100
102
  redis_port: redis_port,
101
103
  redis_db_name: redis_db_name
102
104
  )
103
-
104
- Redis.new(options.merge(url: redis_url))
105
+ pool_size = options.delete(:pool_size) || DEFAULT_POOL_SIZE
106
+ RedisClient.
107
+ config(**options.merge(url: redis_url)).
108
+ new_pool(size: pool_size)
105
109
  end
106
110
 
107
111
  def build_redis_url(redis_host: nil, redis_port: nil, redis_db_name: nil)
@@ -150,7 +154,7 @@ module JWTSessions
150
154
  all_keys = []
151
155
 
152
156
  loop do
153
- cursor, keys = storage.scan(cursor, match: key_pattern, count: 1000)
157
+ cursor, keys = storage.call("SCAN", cursor, match: key_pattern, count: 1000)
154
158
  all_keys |= keys
155
159
 
156
160
  break if cursor == "0"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JWTSessions
4
- VERSION = "2.7.3"
4
+ VERSION = "3.0.0"
5
5
  end
@@ -24,29 +24,28 @@ class TestRedisStoreAdapter < Minitest::Test
24
24
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new(
25
25
  redis_url: "redis://127.0.0.1:6379",
26
26
  ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE },
27
- reconnect_delay: 2,
28
27
  timeout: 8
29
28
  )
30
- options = adapter.storage.instance_variable_get(:@options)
29
+ config = adapter.storage.config
31
30
 
32
- assert_equal 8, options[:timeout]
33
- assert_equal 2, options[:reconnect_delay]
34
- assert_equal 0, options[:ssl_params][:verify_mode]
31
+ assert_equal 8, config.instance_variable_get(:@connect_timeout)
32
+ assert_equal 0, config.instance_variable_get(:@ssl_params)[:verify_mode]
35
33
  end
36
34
 
37
35
  def test_default_url
38
36
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
39
- assert_equal "redis://127.0.0.1:6379/0", adapter.storage.connection[:id]
37
+
38
+ assert_equal "redis://127.0.0.1:6379/0", adapter.storage.config.server_url
40
39
  end
41
40
 
42
41
  def test_url_with_env_var
43
42
  ENV["REDIS_URL"] = "redis://locallol:2018/"
44
43
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
45
- assert_equal "redis://locallol:2018/0", adapter.storage.connection[:id]
44
+ assert_equal "redis://locallol:2018/0", adapter.storage.config.server_url
46
45
 
47
46
  ENV.delete("REDIS_URL")
48
47
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
49
- assert_equal "redis://127.0.0.1:6379/0", adapter.storage.connection[:id]
48
+ assert_equal "redis://127.0.0.1:6379/0", adapter.storage.config.server_url
50
49
  end
51
50
 
52
51
  def test_configuration_via_host_port_and_db
@@ -55,7 +54,7 @@ class TestRedisStoreAdapter < Minitest::Test
55
54
  redis_port: "6372",
56
55
  redis_db_name: "2"
57
56
  )
58
- assert_equal "redis://127.0.0.2:6372/2", adapter.storage.connection[:id]
57
+ assert_equal "redis://127.0.0.2:6372/2", adapter.storage.config.server_url
59
58
  end
60
59
 
61
60
  def test_configuration_via_host_port_and_db_in_module
@@ -64,18 +63,18 @@ class TestRedisStoreAdapter < Minitest::Test
64
63
  JWTSessions.redis_db_name = "2"
65
64
 
66
65
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
67
- assert_equal "redis://127.0.0.2:6372/2", adapter.storage.connection[:id]
66
+ assert_equal "redis://127.0.0.2:6372/2", adapter.storage.config.server_url
68
67
  end
69
68
 
70
69
  def test_configuration_via_redis_url
71
70
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new(redis_url: "redis://127.0.0.2:6322")
72
- assert_equal "redis://127.0.0.2:6322/0", adapter.storage.connection[:id]
71
+ assert_equal "redis://127.0.0.2:6322/0", adapter.storage.config.server_url
73
72
  end
74
73
 
75
74
  def test_configuration_via_redis_url_in_module
76
75
  JWTSessions.redis_url = "redis://127.0.0.2:6322"
77
76
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
78
- assert_equal "redis://127.0.0.2:6322/0", adapter.storage.connection[:id]
77
+ assert_equal "redis://127.0.0.2:6322/0", adapter.storage.config.server_url
79
78
  end
80
79
 
81
80
  def test_configuration_via_redis_client
@@ -83,4 +82,12 @@ class TestRedisStoreAdapter < Minitest::Test
83
82
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new(redis_client: client)
84
83
  assert_equal client, adapter.storage
85
84
  end
85
+
86
+ def test_redis_pool_size
87
+ default_adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
88
+ assert_equal 5, default_adapter.storage.instance_variable_get(:@pool).size
89
+
90
+ adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new(pool_size: 10)
91
+ assert_equal 10, adapter.storage.instance_variable_get(:@pool).size
92
+ end
86
93
  end
@@ -16,9 +16,9 @@ class TestSession < Minitest::Test
16
16
  end
17
17
 
18
18
  def teardown
19
- redis = Redis.new
20
- keys = redis.keys("jwt_*")
21
- keys.each { |k| redis.del(k) }
19
+ redis = RedisClient.new
20
+ keys = redis.call("KEYS", "jwt_*")
21
+ keys.each { |k| redis.call("DEL", k) }
22
22
  end
23
23
 
24
24
  def test_login
@@ -309,8 +309,8 @@ class TestSession < Minitest::Test
309
309
  session.flush_namespaced_access_tokens
310
310
  ruid = session.instance_variable_get(:"@_refresh").uid
311
311
  refresh_token = JWTSessions::RefreshToken.find(ruid, JWTSessions.token_store, namespace)
312
- assert_equal "", refresh_token.access_uid
313
- assert_equal "", refresh_token.access_expiration
312
+ assert_equal "0", refresh_token.access_uid
313
+ assert_equal "0", refresh_token.access_expiration
314
314
 
315
315
  # allows to refresh with un-expired but flushed access token payload
316
316
  session.refresh_by_access_payload do
@@ -320,8 +320,8 @@ class TestSession < Minitest::Test
320
320
  access_token = JWTSessions::AccessToken.find(auid, JWTSessions.token_store)
321
321
  refresh_token = JWTSessions::RefreshToken.find(ruid, JWTSessions.token_store, namespace)
322
322
 
323
- assert_equal false, access_token.uid.size.zero?
324
- assert_equal false, access_token.expiration.size.zero?
323
+ assert "0" != access_token.uid
324
+ assert "0" != access_token.expiration
325
325
  assert_equal access_token.uid.to_s, refresh_token.access_uid
326
326
  assert_equal access_token.expiration.to_s, refresh_token.access_expiration
327
327
  end
@@ -51,14 +51,20 @@ class TestToken < Minitest::Test
51
51
  end
52
52
 
53
53
  def test_ecdsa_token_decode
54
+ # temp: the test is failling for ruby 3 because of openssl-3 issue
55
+ # https://github.com/ruby/openssl/issues/369
56
+ skip if RUBY_VERSION.to_i > 2
57
+
54
58
  JWTSessions.algorithm = "ES256"
55
59
  JWTSessions.private_key = OpenSSL::PKey::EC.new "prime256v1"
56
60
  JWTSessions.private_key.generate_key
57
- JWTSessions.public_key = OpenSSL::PKey::EC.new JWTSessions.private_key
58
- JWTSessions.public_key.private_key = nil
61
+
62
+ JWTSessions.public_key = OpenSSL::PKey::EC.new JWTSessions.private_key
63
+ JWTSessions.public_key.private_key = nil
59
64
 
60
65
  token = JWTSessions::Token.encode(payload)
61
66
  decoded = JWTSessions::Token.decode(token).first
67
+
62
68
  assert_equal payload["user_id"], decoded["user_id"]
63
69
  assert_equal payload["secret"], decoded["secret"]
64
70
  end
@@ -30,7 +30,7 @@ class TestTokenStore < Minitest::Test
30
30
  JWTSessions.redis_port = 6378
31
31
  JWTSessions.token_store = :redis
32
32
 
33
- assert_equal "redis://127.0.0.1:6378/0", JWTSessions.token_store.storage.connection[:id]
33
+ assert_equal "redis://127.0.0.1:6378/0", JWTSessions.token_store.storage.config.server_url
34
34
  end
35
35
 
36
36
  def test_setting_redis_token_store_without_options
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.7.3
4
+ version: 3.0.0
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: 2022-08-26 00:00:00.000000000 Z
11
+ date: 2022-12-27 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.5'
19
+ version: '2.6'
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.5'
29
+ version: '2.6'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '3'
@@ -112,7 +112,7 @@ metadata:
112
112
  changelog_uri: https://github.com/tuwukee/jwt_sessions/blob/master/CHANGELOG.md
113
113
  source_code_uri: https://github.com/tuwukee/jwt_sessions
114
114
  bug_tracker_uri: https://github.com/tuwukee/jwt_sessions/issues
115
- post_install_message:
115
+ post_install_message:
116
116
  rdoc_options: []
117
117
  require_paths:
118
118
  - lib
@@ -127,17 +127,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
127
  - !ruby/object:Gem::Version
128
128
  version: '0'
129
129
  requirements: []
130
- rubygems_version: 3.0.3.1
131
- signing_key:
130
+ rubygems_version: 3.3.7
131
+ signing_key:
132
132
  specification_version: 4
133
133
  summary: JWT Sessions
134
134
  test_files:
135
135
  - test/units/test_jwt_sessions.rb
136
136
  - test/units/test_token_store.rb
137
- - test/units/jwt_sessions/test_csrf_token.rb
138
- - test/units/jwt_sessions/test_access_token.rb
139
- - test/units/jwt_sessions/store_adapters/test_redis_store_adapter.rb
140
137
  - test/units/jwt_sessions/store_adapters/test_memory_store_adapter.rb
141
- - test/units/jwt_sessions/test_token.rb
138
+ - test/units/jwt_sessions/store_adapters/test_redis_store_adapter.rb
139
+ - test/units/jwt_sessions/test_access_token.rb
140
+ - test/units/jwt_sessions/test_csrf_token.rb
142
141
  - test/units/jwt_sessions/test_refresh_token.rb
143
142
  - test/units/jwt_sessions/test_session.rb
143
+ - test/units/jwt_sessions/test_token.rb