jwt_sessions 2.7.4 → 3.0.1

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: 8d8719e8f8b113faf2af6b40f1912d2cf4819527634411ec946a909c67833d31
4
- data.tar.gz: f4e46db88c68b110dc78034925fce8193deab286d5703ea81ccfd2740bca9225
3
+ metadata.gz: 7d38f64697988a31f87a3e1b4e95910f821a24fc0c35cea614b9d4a72f16a0a5
4
+ data.tar.gz: 4b1aecccf844e0d7dc4de866c03b9af136b9b422e7e3caf4ffb4138517e6e771
5
5
  SHA512:
6
- metadata.gz: 6edb6fb526941fda66abcf0cea4a69904e08f4ca0be03ff7514d8c73e9b9f94cb86cb74a948612d62f3a20a2f91c123bce8c5e342b2600c959f0da90f4e0a918
7
- data.tar.gz: b49c7a27800f9b7621565c9e9206a30f547e837668fb0fd683073ff75b062479bb0d51630f28cd165a70ecd767fc44f736795d4d12b480183fe7395b239696ac
6
+ metadata.gz: 075e7f3b2dc0ebf798ab8696ad715badb95d0f485dbf6dc62d059055a65283d11e1250db541c7b90249055bc4424946a8bfcfc916d23c4afdb8d06958b1f52f3
7
+ data.tar.gz: cec03faa24c671b234022742a59689f07c4bd50105a286b03c3b7b1535134c8f95d69c0a29ee47d0d47385590071134d1c82844bdfa6bb2882108b88956f6a47
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## 3.0.1 (December 28, 2022)
2
+
3
+ Support:
4
+
5
+ - fix bug with expire/expireat
6
+
7
+ ## 3.0.0 (December 27, 2022)
8
+
9
+ Features:
10
+
11
+ - replace `redis` with `redis-client`
12
+ - add `pool_size` setting to support concurrency within `redis-client`'s connection pool
13
+
14
+ Support:
15
+
16
+ - upgrade `jwt` to 2.6 in dependencies
17
+
1
18
  ## 2.7.4 (August 31, 2022)
2
19
 
3
20
  Support:
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
@@ -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,21 @@ 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)
36
+ storage.call("EXPIREAT", key, expiration)
36
37
  end
37
38
 
38
39
  def fetch_refresh(uid, namespace, first_match = false)
39
40
  key = first_match ? first_refresh_key(uid) : full_refresh_key(uid, namespace)
40
41
  return {} if key.nil?
41
42
 
42
- values = storage.hmget(key, *REFRESH_KEYS).compact
43
+ values = storage.call("HMGET", key, *REFRESH_KEYS).compact
43
44
  return {} if values.length != REFRESH_KEYS.length
44
45
 
45
46
  REFRESH_KEYS
@@ -57,12 +58,12 @@ module JWTSessions
57
58
  csrf: csrf,
58
59
  namespace: namespace
59
60
  )
60
- storage.hset(key, :expiration, expiration)
61
- storage.expireat(key, expiration)
61
+ storage.call("HSET", key, :expiration, expiration)
62
+ storage.call("EXPIREAT", key, expiration)
62
63
  end
63
64
 
64
65
  def update_refresh(uid:, access_expiration:, access_uid:, csrf:, namespace: nil)
65
- storage.hmset(
66
+ storage.call("HMSET",
66
67
  full_refresh_key(uid, namespace),
67
68
  :csrf, csrf,
68
69
  :access_expiration, access_expiration,
@@ -83,11 +84,11 @@ module JWTSessions
83
84
 
84
85
  def destroy_refresh(uid, namespace)
85
86
  key = full_refresh_key(uid, namespace)
86
- storage.del(key)
87
+ storage.call("DEL", key)
87
88
  end
88
89
 
89
90
  def destroy_access(uid)
90
- storage.del(access_key(uid))
91
+ storage.call("DEL", access_key(uid))
91
92
  end
92
93
 
93
94
  private
@@ -102,8 +103,10 @@ module JWTSessions
102
103
  redis_port: redis_port,
103
104
  redis_db_name: redis_db_name
104
105
  )
105
-
106
- Redis.new(options.merge(url: redis_url))
106
+ pool_size = options.delete(:pool_size) || DEFAULT_POOL_SIZE
107
+ RedisClient.
108
+ config(**options.merge(url: redis_url)).
109
+ new_pool(size: pool_size)
107
110
  end
108
111
 
109
112
  def build_redis_url(redis_host: nil, redis_port: nil, redis_db_name: nil)
@@ -152,7 +155,7 @@ module JWTSessions
152
155
  all_keys = []
153
156
 
154
157
  loop do
155
- cursor, keys = storage.scan(cursor, match: key_pattern, count: 1000)
158
+ cursor, keys = storage.call("SCAN", cursor, match: key_pattern, count: 1000)
156
159
  all_keys |= keys
157
160
 
158
161
  break if cursor == "0"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JWTSessions
4
- VERSION = "2.7.4"
4
+ VERSION = "3.0.1"
5
5
  end
@@ -26,25 +26,26 @@ class TestRedisStoreAdapter < Minitest::Test
26
26
  ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE },
27
27
  timeout: 8
28
28
  )
29
- options = adapter.storage.instance_variable_get(:@options)
29
+ config = adapter.storage.config
30
30
 
31
- assert_equal 8, options[:timeout]
32
- 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]
33
33
  end
34
34
 
35
35
  def test_default_url
36
36
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
37
- 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
38
39
  end
39
40
 
40
41
  def test_url_with_env_var
41
42
  ENV["REDIS_URL"] = "redis://locallol:2018/"
42
43
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
43
- assert_equal "redis://locallol:2018/0", adapter.storage.connection[:id]
44
+ assert_equal "redis://locallol:2018/0", adapter.storage.config.server_url
44
45
 
45
46
  ENV.delete("REDIS_URL")
46
47
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
47
- 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
48
49
  end
49
50
 
50
51
  def test_configuration_via_host_port_and_db
@@ -53,7 +54,7 @@ class TestRedisStoreAdapter < Minitest::Test
53
54
  redis_port: "6372",
54
55
  redis_db_name: "2"
55
56
  )
56
- 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
57
58
  end
58
59
 
59
60
  def test_configuration_via_host_port_and_db_in_module
@@ -62,18 +63,18 @@ class TestRedisStoreAdapter < Minitest::Test
62
63
  JWTSessions.redis_db_name = "2"
63
64
 
64
65
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
65
- 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
66
67
  end
67
68
 
68
69
  def test_configuration_via_redis_url
69
70
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new(redis_url: "redis://127.0.0.2:6322")
70
- 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
71
72
  end
72
73
 
73
74
  def test_configuration_via_redis_url_in_module
74
75
  JWTSessions.redis_url = "redis://127.0.0.2:6322"
75
76
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
76
- 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
77
78
  end
78
79
 
79
80
  def test_configuration_via_redis_client
@@ -81,4 +82,21 @@ class TestRedisStoreAdapter < Minitest::Test
81
82
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new(redis_client: client)
82
83
  assert_equal client, adapter.storage
83
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
93
+
94
+ def test_persist_access
95
+ adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
96
+ expire_at = Time.now.to_i + 10
97
+ adapter.persist_access("test_access_token_exp", "test_csrf", expire_at)
98
+ ttl = adapter.storage.call("TTL", "jwt__access_test_access_token_exp")
99
+ assert_operator ttl, :<=, 10
100
+ adapter.storage.call("DEL", "jwt__access_test_access_token_exp")
101
+ end
84
102
  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
@@ -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.4
4
+ version: 3.0.1
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-31 00:00:00.000000000 Z
11
+ date: 2022-12-28 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