jwt_sessions 2.0.0 → 2.1.0

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
  SHA1:
3
- metadata.gz: 6ab2b9607a84bdecaea7ec538b3ba194ae0d57e4
4
- data.tar.gz: 3ade912f52efd6078fb676697187145c23e39024
3
+ metadata.gz: 7981af52568346a34f4c308e76b19b88ddc264ea
4
+ data.tar.gz: 48fe0cb349266922f0124a918c14e4c79c10d28b
5
5
  SHA512:
6
- metadata.gz: 7761b2f89cf64203f8f82cef4e95c28f6ea602cee0a22d56318bbfd1299cb6e2c3b50ad41b840fddd458dc53b0b249b3d7820a99405b67b2ffb532b900f15d51
7
- data.tar.gz: d4e087880bfc893c983c7187d2c206c521efe3beb0c0c245161e0c614bc59868a05c474c9479a36f778966c4ab017c220fd9e866448afd83f9444c59f5f5b33c
6
+ metadata.gz: 8c275a6504519c3447c36b9557223ba5403d87d590ba9d4d7215fc4f6580021a00a296b6daa71ef2e7f15c1fa61dd7fe0d1f9b62813ae63e93381e342a3e2640
7
+ data.tar.gz: cafceae22f54838b7745f4e26deaf5eba969212f235552e1d2fde547608f6219e76a4482135a02e5b4cc94818dc5d1ec5c256c79b67907b6531e06df980dc6ff
data/README.md CHANGED
@@ -15,7 +15,7 @@ XSS/CSRF safe JWT auth designed for SPA
15
15
  * [Non-Rails usage](#non-rails-usage)
16
16
  - [Configuration](#configuration)
17
17
  + [Redis](#redis)
18
- + [JWT encryption](#jwt-encryption)
18
+ + [JWT signature](#jwt-signature)
19
19
  + [Request headers and cookies names](#request-headers-and-cookies-names)
20
20
  + [Expiration time](#expiration-time)
21
21
  + [CSRF and cookies](#csrf-and-cookies)
@@ -290,11 +290,11 @@ Default token store configurations
290
290
  ```ruby
291
291
  JWTSessions.redis_host = '127.0.0.1'
292
292
  JWTSessions.redis_port = '6379'
293
- JWTSessions.redis_db_name = 'jwtokens'
293
+ JWTSessions.redis_db_name = '0'
294
294
  JWTSessions.token_prefix = 'jwt_' # used for redis db keys
295
295
  ```
296
296
 
297
- ##### JWT encryption
297
+ ##### JWT signature
298
298
 
299
299
  ```ruby
300
300
  JWTSessions.algorithm = 'HS256'
@@ -38,6 +38,21 @@ module JWTSessions
38
38
  def destroy(uid, store)
39
39
  store.destroy_access(uid)
40
40
  end
41
+
42
+ # AccessToken's find method cannot be used to retrieve token's payload
43
+ # or any other information but is intended to identify if the token is present
44
+ # and to retrieve session's CSRF token
45
+ def find(uid, store)
46
+ token_attrs = store.fetch_access(uid)
47
+ raise Errors::Unauthorized, 'Access token not found' if token_attrs.empty?
48
+ build_with_token_attrs(store, uid, token_attrs)
49
+ end
50
+
51
+ private
52
+
53
+ def build_with_token_attrs(store, uid, token_attrs)
54
+ new(token_attrs[:csrf], {}, store, uid)
55
+ end
41
56
  end
42
57
  end
43
58
  end
@@ -4,5 +4,6 @@ module JWTSessions
4
4
  class Malconfigured < Error; end
5
5
  class InvalidPayload < Error; end
6
6
  class Unauthorized < Error; end
7
+ class ClaimsVerification < Unauthorized; end
7
8
  end
8
9
  end
@@ -63,11 +63,13 @@ module JWTSessions
63
63
  flush_by_uid(ruid)
64
64
  end
65
65
 
66
+ # flush the session by refresh token
66
67
  def flush_by_token(token)
67
68
  uid = token_uid(token, :refresh, @refresh_claims)
68
69
  flush_by_uid(uid)
69
70
  end
70
71
 
72
+ # flush the session by refresh token uid
71
73
  def flush_by_uid(uid)
72
74
  token = retrieve_refresh_token(uid)
73
75
 
@@ -75,6 +77,15 @@ module JWTSessions
75
77
  token.destroy
76
78
  end
77
79
 
80
+ # flush access tokens only and keep refresh
81
+ def flush_namespaced_access_tokens
82
+ return 0 unless namespace
83
+ tokens = RefreshToken.all(namespace, store)
84
+ tokens.each do |token|
85
+ AccessToken.destroy(token.access_uid, store)
86
+ end.count
87
+ end
88
+
78
89
  def flush_namespaced
79
90
  return 0 unless namespace
80
91
  tokens = RefreshToken.all(namespace, store)
@@ -13,6 +13,8 @@ module JWTSessions
13
13
  def decode(token, claims = {})
14
14
  decode_options = { algorithm: JWTSessions.algorithm }.merge(JWTSessions.jwt_options.to_h).merge(claims)
15
15
  JWT.decode(token, JWTSessions.public_key, JWTSessions.validate?, decode_options)
16
+ rescue JWT::InvalidIssuerError, JWT::InvalidIatError, JWT::InvalidAudError, JWT::InvalidSubError, JWT::InvalidJtiError => e
17
+ raise Errors::ClaimsVerification, e.message
16
18
  rescue JWT::DecodeError => e
17
19
  raise Errors::Unauthorized, e.message
18
20
  rescue StandardError
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JWTSessions
4
- VERSION = '2.0.0'
4
+ VERSION = '2.1.0'
5
5
  end
data/lib/jwt_sessions.rb CHANGED
@@ -36,7 +36,7 @@ module JWTSessions
36
36
 
37
37
  DEFAULT_REDIS_HOST = '127.0.0.1'
38
38
  DEFAULT_REDIS_PORT = '6379'
39
- DEFAULT_REDIS_DB_NAME = 'jwtokens'
39
+ DEFAULT_REDIS_DB_NAME = '0'
40
40
  DEFAULT_TOKEN_PREFIX = 'jwt_'
41
41
  DEFAULT_ALGORITHM = 'HS256'
42
42
  DEFAULT_ACCESS_EXP_TIME = 3600 # 1 hour in seconds
@@ -166,6 +166,25 @@ class TestSession < Minitest::Test
166
166
  assert_equal refresh_token.token, JWTSessions::RefreshToken.find(refresh_token.uid, JWTSessions.token_store, nil).token
167
167
  end
168
168
 
169
+ def test_flush_namespaced_access_tokens
170
+ namespace = 'test_namespace'
171
+ @session1 = JWTSessions::Session.new(payload: payload, namespace: namespace)
172
+ @session1.login
173
+ refresh_token = @session1.instance_variable_get(:"@_refresh")
174
+ access_token = @session1.instance_variable_get(:"@_access")
175
+ uid = access_token.uid
176
+ ruid = refresh_token.uid
177
+
178
+ assert_equal access_token.csrf, JWTSessions::AccessToken.find(uid, JWTSessions.token_store).csrf
179
+ flushed_count = @session1.flush_namespaced_access_tokens
180
+
181
+ assert_equal 1, flushed_count
182
+ assert_raises JWTSessions::Errors::Unauthorized do
183
+ JWTSessions::AccessToken.find(uid, JWTSessions.token_store)
184
+ end
185
+ assert_equal ruid, JWTSessions::RefreshToken.find(ruid, JWTSessions.token_store, namespace).uid
186
+ end
187
+
169
188
  def test_flush_all
170
189
  refresh_token = @session.instance_variable_get(:"@_refresh")
171
190
  flushed_count = JWTSessions::Session.flush_all
@@ -79,7 +79,7 @@ class TestToken < Minitest::Test
79
79
  decoded = JWTSessions::Token.decode(token, { sub: 'subject' }).first
80
80
  assert_equal payload['user_id'], decoded['user_id']
81
81
  assert_equal payload['secret'], decoded['secret']
82
- assert_raises JWTSessions::Errors::Unauthorized do
82
+ assert_raises JWTSessions::Errors::ClaimsVerification do
83
83
  JWTSessions::Token.decode(token, { sub: 'different subject' })
84
84
  end
85
85
  end
@@ -91,7 +91,7 @@ class TestToken < Minitest::Test
91
91
  decoded = JWTSessions::Token.decode(token, { iss: 'Me' }).first
92
92
  assert_equal payload['user_id'], decoded['user_id']
93
93
  assert_equal payload['secret'], decoded['secret']
94
- assert_raises JWTSessions::Errors::Unauthorized do
94
+ assert_raises JWTSessions::Errors::ClaimsVerification do
95
95
  JWTSessions::Token.decode(token, { iss: 'Not Me' })
96
96
  end
97
97
  end
@@ -103,7 +103,7 @@ class TestToken < Minitest::Test
103
103
  decoded = JWTSessions::Token.decode(token, { aud: ['young'] }).first
104
104
  assert_equal payload['user_id'], decoded['user_id']
105
105
  assert_equal payload['secret'], decoded['secret']
106
- assert_raises JWTSessions::Errors::Unauthorized do
106
+ assert_raises JWTSessions::Errors::ClaimsVerification do
107
107
  JWTSessions::Token.decode(token, { aud: ['adult'] })
108
108
  end
109
109
  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.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yulia Oletskaya
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-17 00:00:00.000000000 Z
11
+ date: 2018-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jwt