jwt_sessions 2.7.0 → 2.7.4

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: ad42d33af309b3295e9aa6402179df2a9a0ac5e17618d133427e27edafca9578
4
- data.tar.gz: e67b97b9bf3a2aec4bba3f66cc517d4dad03bcb4ce73269147cce31bcd9d85d4
3
+ metadata.gz: 8d8719e8f8b113faf2af6b40f1912d2cf4819527634411ec946a909c67833d31
4
+ data.tar.gz: f4e46db88c68b110dc78034925fce8193deab286d5703ea81ccfd2740bca9225
5
5
  SHA512:
6
- metadata.gz: fe6bc8a993388688a85d6b86ea139ab8d3123b628db77181fa4db6ba68d92c0080ca16fdfcaeb3567be9f2a07896df711cb9edb9c7845d6a226408e6fda00de9
7
- data.tar.gz: 712ea681644f82710f5d561a96e78df86c1c3e4c225b8535a9d1cd2e03bcb363d93e4b42764847b786461e26f6f9440a3f85b026e02fa557c647a5866eef70dc
6
+ metadata.gz: 6edb6fb526941fda66abcf0cea4a69904e08f4ca0be03ff7514d8c73e9b9f94cb86cb74a948612d62f3a20a2f91c123bce8c5e342b2600c959f0da90f4e0a918
7
+ data.tar.gz: b49c7a27800f9b7621565c9e9206a30f547e837668fb0fd683073ff75b062479bb0d51630f28cd165a70ecd767fc44f736795d4d12b480183fe7395b239696ac
data/CHANGELOG.md CHANGED
@@ -1,3 +1,28 @@
1
+ ## 2.7.4 (August 31, 2022)
2
+
3
+ Support:
4
+
5
+ - compatibility with redis 5.0
6
+
7
+ ## 2.7.3 (August 26, 2022)
8
+
9
+ Support:
10
+
11
+ - compatibility with jwt 2.5
12
+ - add rspec to development deps
13
+
14
+ ## 2.7.2 (January 24, 2022)
15
+
16
+ Bugfixes:
17
+
18
+ - 2.7.1 version didn't include the correct patch
19
+
20
+ ## 2.7.1 (January 22, 2022)
21
+
22
+ Bugfixes:
23
+
24
+ - Correctly init namespaced refresh tokens when fetching all tokens from Redis
25
+
1
26
  ## 2.7.0 (October 05, 2021)
2
27
 
3
28
  Features:
data/README.md CHANGED
@@ -409,11 +409,11 @@ jwt_sessions only uses `exp` claim by default when it decodes tokens and you can
409
409
  setting `jwt_options`. You can also specify leeway to account for clock skew.
410
410
 
411
411
  ```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
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
417
417
  ```
418
418
 
419
419
  To pass options like `sub`, `aud`, `iss`, or leeways you should specify a method called `token_claims` in your controller.
@@ -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]
@@ -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
 
@@ -37,10 +37,15 @@ module JWTSessions
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.hmget(key, *REFRESH_KEYS).compact
42
43
  return {} if values.length != REFRESH_KEYS.length
43
- REFRESH_KEYS.each_with_index.each_with_object({}) { |(key, index), acc| acc[key] = values[index] }
44
+
45
+ REFRESH_KEYS
46
+ .each_with_index
47
+ .each_with_object({}) { |(key, index), acc| acc[key] = values[index] }
48
+ .merge({ namespace: namespace })
44
49
  end
45
50
 
46
51
  def persist_refresh(uid:, access_expiration:, access_uid:, csrf:, expiration:, namespace: nil)
@@ -69,7 +74,10 @@ module JWTSessions
69
74
  keys_in_namespace = scan_keys(refresh_key("*", namespace))
70
75
  (keys_in_namespace || []).each_with_object({}) do |key, acc|
71
76
  uid = uid_from_key(key)
72
- acc[uid] = fetch_refresh(uid, namespace)
77
+ # to be able to properly initialize namespaced tokens extract their namespaces
78
+ # and pass down to fetch_refresh
79
+ token_namespace = namespace.to_s.empty? ? namespace_from_key(key) : namespace
80
+ acc[uid] = fetch_refresh(uid, token_namespace)
73
81
  end
74
82
  end
75
83
 
@@ -131,6 +139,14 @@ module JWTSessions
131
139
  key.split("_").last
132
140
  end
133
141
 
142
+ def namespace_from_key(key)
143
+ ns_regexp.match(key)&.[](:namespace)
144
+ end
145
+
146
+ def ns_regexp
147
+ @ns_regexp ||= Regexp.new("#{prefix}_(?<namespace>.+)_refresh")
148
+ end
149
+
134
150
  def scan_keys(key_pattern)
135
151
  cursor = 0
136
152
  all_keys = []
@@ -13,7 +13,7 @@ module JWTSessions
13
13
  end
14
14
 
15
15
  def decode(token, claims = {})
16
- decode_options = { algorithm: JWTSessions.algorithm }.merge(JWTSessions.jwt_options.to_h).merge(claims)
16
+ decode_options = { algorithm: JWTSessions.algorithm }.merge(JWTSessions.jwt_options).merge(claims)
17
17
  JWT.decode(token, JWTSessions.public_key, JWTSessions.validate?, decode_options)
18
18
  rescue JWT::ExpiredSignature => e
19
19
  raise Errors::Expired, e.message
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JWTSessions
4
- VERSION = "2.7.0"
4
+ VERSION = "2.7.4"
5
5
  end
data/lib/jwt_sessions.rb CHANGED
@@ -21,8 +21,6 @@ module JWTSessions
21
21
 
22
22
  NONE = "none"
23
23
 
24
- JWTOptions = Struct.new(*JWT::DefaultOptions::DEFAULT_OPTIONS.keys)
25
-
26
24
  DEFAULT_SETTINGS_KEYS = %i[access_cookie
27
25
  access_exp_time
28
26
  access_header
@@ -66,7 +64,7 @@ module JWTSessions
66
64
  end
67
65
 
68
66
  def jwt_options
69
- @jwt_options ||= JWTOptions.new(*JWT::DefaultOptions::DEFAULT_OPTIONS.values)
67
+ @jwt_options ||= JWT::Configuration::Container.new.decode.to_h
70
68
  end
71
69
 
72
70
  def algorithm=(algo)
@@ -24,13 +24,11 @@ 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
29
  options = adapter.storage.instance_variable_get(:@options)
31
30
 
32
31
  assert_equal 8, options[:timeout]
33
- assert_equal 2, options[:reconnect_delay]
34
32
  assert_equal 0, options[:ssl_params][:verify_mode]
35
33
  end
36
34
 
@@ -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
@@ -24,7 +24,7 @@ class TestToken < Minitest::Test
24
24
 
25
25
  def teardown
26
26
  JWTSessions.algorithm = JWTSessions::DEFAULT_ALGORITHM
27
- JWTSessions.instance_variable_set(:"@jwt_options", JWTSessions::JWTOptions.new(*JWT::DefaultOptions::DEFAULT_OPTIONS.values))
27
+ JWTSessions.instance_variable_set(:"@jwt_options", JWT::Configuration::Container.new.decode.to_h)
28
28
  end
29
29
 
30
30
  def test_rsa_token_decode
@@ -73,7 +73,7 @@ class TestToken < Minitest::Test
73
73
 
74
74
  def test_token_sub_claim
75
75
  JWTSessions.encryption_key = "abcdefghijklmnopqrstuvwxyzABCDEF"
76
- JWTSessions.jwt_options.verify_sub = true
76
+ JWTSessions.jwt_options[:verify_sub] = true
77
77
  token = JWTSessions::Token.encode(payload.merge(sub: "subject"))
78
78
  decoded = JWTSessions::Token.decode(token, { sub: "subject" }).first
79
79
  assert_equal payload["user_id"], decoded["user_id"]
@@ -85,7 +85,7 @@ class TestToken < Minitest::Test
85
85
 
86
86
  def test_token_iss_claim
87
87
  JWTSessions.encryption_key = "abcdefghijklmnopqrstuvwxyzABCDEF"
88
- JWTSessions.jwt_options.verify_iss = true
88
+ JWTSessions.jwt_options[:verify_iss] = true
89
89
  token = JWTSessions::Token.encode(payload.merge(iss: "Me"))
90
90
  decoded = JWTSessions::Token.decode(token, { iss: "Me" }).first
91
91
  assert_equal payload["user_id"], decoded["user_id"]
@@ -97,7 +97,7 @@ class TestToken < Minitest::Test
97
97
 
98
98
  def test_token_aud_claim
99
99
  JWTSessions.encryption_key = "abcdefghijklmnopqrstuvwxyzABCDEF"
100
- JWTSessions.jwt_options.verify_aud = true
100
+ JWTSessions.jwt_options[:verify_aud] = true
101
101
  token = JWTSessions::Token.encode(payload.merge(aud: ["young", "old"]))
102
102
  decoded = JWTSessions::Token.decode(token, { aud: ["young"] }).first
103
103
  assert_equal payload["user_id"], decoded["user_id"]
@@ -109,7 +109,7 @@ class TestToken < Minitest::Test
109
109
 
110
110
  def test_token_leeway_decode
111
111
  JWTSessions.encryption_key = "abcdefghijklmnopqrstuvwxyzABCDEF"
112
- JWTSessions.jwt_options.leeway = 50
112
+ JWTSessions.jwt_options[:leeway] = 50
113
113
  token = JWTSessions::Token.encode(payload.merge("exp" => Time.now.to_i - 20))
114
114
  decoded = JWTSessions::Token.decode(token).first
115
115
  assert_equal payload["user_id"], decoded["user_id"]
metadata CHANGED
@@ -1,22 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jwt_sessions
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.0
4
+ version: 2.7.4
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: 2021-10-05 00:00:00.000000000 Z
11
+ date: 2022-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jwt
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.2.3
19
+ version: '2.5'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '3'
@@ -24,9 +24,9 @@ dependencies:
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - ">="
27
+ - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: 2.2.3
29
+ version: '2.5'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '3'
@@ -58,6 +58,20 @@ dependencies:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '12.3'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.11'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.11'
61
75
  description: XSS/CSRF safe JWT auth designed for SPA
62
76
  email: yulia.oletskaya@gmail.com
63
77
  executables: []
@@ -98,7 +112,7 @@ metadata:
98
112
  changelog_uri: https://github.com/tuwukee/jwt_sessions/blob/master/CHANGELOG.md
99
113
  source_code_uri: https://github.com/tuwukee/jwt_sessions
100
114
  bug_tracker_uri: https://github.com/tuwukee/jwt_sessions/issues
101
- post_install_message:
115
+ post_install_message:
102
116
  rdoc_options: []
103
117
  require_paths:
104
118
  - lib
@@ -113,8 +127,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
127
  - !ruby/object:Gem::Version
114
128
  version: '0'
115
129
  requirements: []
116
- rubygems_version: 3.2.5
117
- signing_key:
130
+ rubygems_version: 3.0.3.1
131
+ signing_key:
118
132
  specification_version: 4
119
133
  summary: JWT Sessions
120
134
  test_files: