jwt_sessions 2.6.0 → 2.7.3

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: 8a485796c7aa19c00c79992111ed0135c0ec93af6e88aff80b233be779bb2301
4
- data.tar.gz: d0b89a924589aa8450cfcaefb2061674db4d61cb32ed5ace92f1cab021db1fb1
3
+ metadata.gz: ed69732617f15f4c07c0fb37d3ad938807224b729f136d24755a90f58b7b28ab
4
+ data.tar.gz: 27bee3f1c2bd4b099b0dadea703143d70e6abf1aaa6e5556f67515dfbc6f2e5b
5
5
  SHA512:
6
- metadata.gz: e0bef3934719502d51f1299b210fad2df87360ef91cc3471384c3840870f3d548f43c5c5c1ff89a33e9e8847b706f9b7e1d2c240f288a21a16533369d8b0fce5
7
- data.tar.gz: cd8b450b1a09e13290e3ac6ec5bcd17cf52c7314f01044ca1c2888321816585ff27eb7ae7b3935f5aa388fec3c11d9b8ebb0fe2c5fdde5a99cbc390932c4a646
6
+ metadata.gz: a0a81d8d8013a1393b441ddd15ec34fb57ceb0bd3198f9ee4a2554dff653efbe4379ad6992d1a8678895e0391f45626068a2f16b422ad8c658b7a086a08241d3
7
+ data.tar.gz: 46e744a4512da3d90b54f6552c42f35c7b3b3d25a9d73292058ac5782102ed9d9c77ac6a734a865b40e2fcccd675257cc5c41d27be45bd5fde758e8d6c97537f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ ## 2.7.3 (August 26, 2022)
2
+
3
+ Bugfixes:
4
+
5
+ - compatibility with jwt 2.5
6
+
7
+ Support:
8
+
9
+ - add rspec to development deps
10
+
11
+ ## 2.7.2 (January 24, 2022)
12
+
13
+ Bugfixes:
14
+
15
+ - 2.7.1 version didn't include the correct patch
16
+
17
+ ## 2.7.1 (January 22, 2022)
18
+
19
+ Bugfixes:
20
+
21
+ - Correctly init namespaced refresh tokens when fetching all tokens from Redis
22
+
23
+ ## 2.7.0 (October 05, 2021)
24
+
25
+ Features:
26
+
27
+ - added redis_client setting to JWTSessions::StoreAdapters::RedisStoreAdapter
28
+
1
29
  ## 2.6.0 (June 01, 2021)
2
30
 
3
31
  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.
@@ -378,6 +378,12 @@ JWTSessions.token_store = :redis, {
378
378
  }
379
379
  ```
380
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
+
381
387
  ##### JWT signature
382
388
 
383
389
  ```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]
@@ -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)
@@ -65,7 +72,10 @@ module JWTSessions
65
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
 
@@ -127,6 +137,14 @@ module JWTSessions
127
137
  key.split("_").last
128
138
  end
129
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
+
130
148
  def scan_keys(key_pattern)
131
149
  cursor = 0
132
150
  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.6.0"
4
+ VERSION = "2.7.3"
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)
@@ -77,4 +77,10 @@ class TestRedisStoreAdapter < Minitest::Test
77
77
  adapter = JWTSessions::StoreAdapters::RedisStoreAdapter.new
78
78
  assert_equal "redis://127.0.0.2:6322/0", adapter.storage.connection[:id]
79
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
80
86
  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.6.0
4
+ version: 2.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yulia Oletskaya
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-01 00:00:00.000000000 Z
11
+ date: 2022-08-26 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: []
@@ -113,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
127
  - !ruby/object:Gem::Version
114
128
  version: '0'
115
129
  requirements: []
116
- rubygems_version: 3.0.3
130
+ rubygems_version: 3.0.3.1
117
131
  signing_key:
118
132
  specification_version: 4
119
133
  summary: JWT Sessions