jwt_sessions 2.5.1 → 2.7.2

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: 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: