jwt_sessions 1.1.0 → 1.2.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 +4 -4
- data/README.md +39 -1
- data/lib/jwt_sessions.rb +4 -2
- data/lib/jwt_sessions/authorization.rb +5 -0
- data/lib/jwt_sessions/redis_token_store.rb +38 -13
- data/lib/jwt_sessions/refresh_token.rb +38 -19
- data/lib/jwt_sessions/session.rb +48 -7
- data/lib/jwt_sessions/version.rb +1 -1
- data/test/units/jwt_sessions/test_refresh_token.rb +5 -4
- data/test/units/jwt_sessions/test_session.rb +64 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a82e7a774b3c7707f9766cab5daaa7931c02575b
|
4
|
+
data.tar.gz: b31598139258b52483ccd593feae380c240d1c24
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c34675a2622944e5e715302bea401442b335abbaeede9b3f77829cee3e7a1d0d1ecc22dc6874ec23954a50f1b91e110b5ab681b3bed538f8dedc8384f67a20b6
|
7
|
+
data.tar.gz: 1d7fb0b9052c9a1df4610282b1ab39e63b9a35d0fd5b77a5d35f83417ff8d0cd52d489f470a3feecf9ede8cffa568301801ab7e1262316be0c559dcf0e0296cf
|
data/README.md
CHANGED
@@ -20,6 +20,8 @@ XSS/CSRF safe JWT auth designed for SPA
|
|
20
20
|
+ [Expiration time](#expiration-time)
|
21
21
|
+ [CSRF and cookies](#csrf-and-cookies)
|
22
22
|
+ [Refresh token hijack protection](#refresh-token-hijack-protection)
|
23
|
+
- [Flush Sessions](#flush-sessions)
|
24
|
+
+ [Sessions Namespace](#sessions-namespace)
|
23
25
|
- [Examples](#examples)
|
24
26
|
- [TODO](#todo)
|
25
27
|
- [Contributing](#contributing)
|
@@ -82,7 +84,7 @@ JWTSessions.algorithm = 'HS256'
|
|
82
84
|
JWTSessions.encryption_key = Rails.application.secrets.secret_jwt_encryption_key
|
83
85
|
```
|
84
86
|
|
85
|
-
Most of the encryption algorithms require private and public keys to sign a token, yet HMAC only require a single key, so you can use a shortcat `
|
87
|
+
Most of the encryption algorithms require private and public keys to sign a token, yet HMAC only require a single key, so you can use a shortcat `encryption_key` to sign the token. For other algorithms you must specify a private and public keys separately.
|
86
88
|
|
87
89
|
```ruby
|
88
90
|
JWTSessions.algorithm = 'RS256'
|
@@ -381,6 +383,42 @@ session = JwtSessions::Session.new(payload: payload)
|
|
381
383
|
session.refresh(refresh_token) { |refresh_token_uid, access_token_expiration| ... }
|
382
384
|
```
|
383
385
|
|
386
|
+
## Flush Sessions
|
387
|
+
|
388
|
+
Flush session by refresh token. The method returns number of flushed sessions.
|
389
|
+
|
390
|
+
```ruby
|
391
|
+
session = JWTSessions::Session.new
|
392
|
+
tokens = session.login
|
393
|
+
session.flush_by_token(tokens[:refresh]) # => 1
|
394
|
+
```
|
395
|
+
|
396
|
+
Or by refresh token UID
|
397
|
+
|
398
|
+
```ruby
|
399
|
+
session.flush_by_uid(uid) # => 1
|
400
|
+
```
|
401
|
+
|
402
|
+
##### Sessions namespace
|
403
|
+
|
404
|
+
It's possible to group sessions by custom namespaces
|
405
|
+
|
406
|
+
```ruby
|
407
|
+
session = JWTSessions::Session.new(namespace: 'account-1')
|
408
|
+
```
|
409
|
+
|
410
|
+
and selectively flush sessions by namespace
|
411
|
+
|
412
|
+
```ruby
|
413
|
+
session = JWTSessions::Session.new(namespace: 'ie-sessions')
|
414
|
+
session.flush_namespaced # will flush all sessions that belong to the same namespace
|
415
|
+
```
|
416
|
+
|
417
|
+
To force flush of all app sessions
|
418
|
+
```ruby
|
419
|
+
JWTSessions::Session.flush_all
|
420
|
+
```
|
421
|
+
|
384
422
|
## Examples
|
385
423
|
|
386
424
|
[Rails API](test/support/dummy_api) \
|
data/lib/jwt_sessions.rb
CHANGED
@@ -25,7 +25,6 @@ module JWTSessions
|
|
25
25
|
DEFAULT_SETTINGS_KEYS = %i[access_cookie
|
26
26
|
access_exp_time
|
27
27
|
access_header
|
28
|
-
algorithm
|
29
28
|
csrf_header
|
30
29
|
redis_db_name
|
31
30
|
redis_host
|
@@ -74,6 +73,10 @@ module JWTSessions
|
|
74
73
|
@algorithm = algo
|
75
74
|
end
|
76
75
|
|
76
|
+
def algorithm
|
77
|
+
@algorithm ||= DEFAULT_ALGORITHM
|
78
|
+
end
|
79
|
+
|
77
80
|
def token_store
|
78
81
|
RedisTokenStore.instance(redis_host, redis_port, redis_db_name, token_prefix)
|
79
82
|
end
|
@@ -110,7 +113,6 @@ module JWTSessions
|
|
110
113
|
Time.now.to_i + refresh_exp_time.to_i
|
111
114
|
end
|
112
115
|
|
113
|
-
|
114
116
|
def header_by(token_type)
|
115
117
|
send("#{token_type}_header")
|
116
118
|
end
|
@@ -16,6 +16,7 @@ module JWTSessions
|
|
16
16
|
end
|
17
17
|
# triggers token decode and jwt claim checks
|
18
18
|
payload
|
19
|
+
invalid_authorization unless session_exists?(token_type)
|
19
20
|
check_csrf(token_type)
|
20
21
|
end
|
21
22
|
end
|
@@ -50,6 +51,10 @@ module JWTSessions
|
|
50
51
|
JWTSessions::Session.new.valid_csrf?(found_token, csrf_token, token_type)
|
51
52
|
end
|
52
53
|
|
54
|
+
def session_exists?(token_type)
|
55
|
+
JWTSessions::Session.new.session_exists?(found_token, token_type)
|
56
|
+
end
|
57
|
+
|
53
58
|
def cookieless_auth(token_type)
|
54
59
|
@_csrf_check = false
|
55
60
|
@_raw_token = token_from_headers(token_type)
|
@@ -43,26 +43,38 @@ module JWTSessions
|
|
43
43
|
store.expireat(key, expiration)
|
44
44
|
end
|
45
45
|
|
46
|
-
def fetch_refresh(uid)
|
47
|
-
keys = [
|
48
|
-
values = store.hmget(refresh_key(uid), *keys).compact
|
46
|
+
def fetch_refresh(uid, namespace)
|
47
|
+
keys = %i[csrf access_uid access_expiration expiration]
|
48
|
+
values = store.hmget(refresh_key(uid, namespace), *keys).compact
|
49
49
|
return {} if values.length != keys.length
|
50
|
-
keys.each_with_index.
|
50
|
+
keys.each_with_index.each_with_object({}) { |(key, index), acc| acc[key] = values[index]; }
|
51
51
|
end
|
52
52
|
|
53
|
-
def persist_refresh(uid, access_expiration, access_uid, csrf, expiration)
|
54
|
-
|
55
|
-
|
53
|
+
def persist_refresh(uid, access_expiration, access_uid, csrf, expiration, namespace = nil)
|
54
|
+
ns = namespace || ''
|
55
|
+
key = refresh_key(uid, ns)
|
56
|
+
update_refresh(uid, access_expiration, access_uid, csrf, ns)
|
56
57
|
store.hset(key, :expiration, expiration)
|
57
58
|
store.expireat(key, expiration)
|
58
59
|
end
|
59
60
|
|
60
|
-
def update_refresh(uid, access_expiration, access_uid, csrf)
|
61
|
-
store.hmset(refresh_key(uid
|
61
|
+
def update_refresh(uid, access_expiration, access_uid, csrf, namespace = nil)
|
62
|
+
store.hmset(refresh_key(uid, namespace),
|
63
|
+
:csrf, csrf,
|
64
|
+
:access_expiration, access_expiration,
|
65
|
+
:access_uid, access_uid)
|
62
66
|
end
|
63
67
|
|
64
|
-
def
|
65
|
-
store.
|
68
|
+
def all_in_namespace(namespace)
|
69
|
+
keys = store.keys(refresh_key('*', namespace))
|
70
|
+
(keys || []).each_with_object({}) do |key, acc|
|
71
|
+
uid = uid_from_key(key)
|
72
|
+
acc[uid] = fetch_refresh(uid, namespace)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def destroy_refresh(uid, namespace)
|
77
|
+
store.del(refresh_key(uid, namespace))
|
66
78
|
end
|
67
79
|
|
68
80
|
def destroy_access(uid)
|
@@ -75,8 +87,21 @@ module JWTSessions
|
|
75
87
|
"#{prefix}_access_#{uid}"
|
76
88
|
end
|
77
89
|
|
78
|
-
def refresh_key(uid)
|
79
|
-
|
90
|
+
def refresh_key(uid, namespace = nil)
|
91
|
+
if namespace
|
92
|
+
"#{prefix}_#{namespace}_refresh_#{uid}"
|
93
|
+
else
|
94
|
+
wildcard_refresh_key(uid)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def wildcard_refresh_key(uid)
|
99
|
+
keys = store.keys(refresh_key(uid, '*')) || []
|
100
|
+
keys.first
|
101
|
+
end
|
102
|
+
|
103
|
+
def uid_from_key(key)
|
104
|
+
key.split('_').last
|
80
105
|
end
|
81
106
|
end
|
82
107
|
end
|
@@ -2,39 +2,58 @@
|
|
2
2
|
|
3
3
|
module JWTSessions
|
4
4
|
class RefreshToken
|
5
|
-
attr_reader :expiration, :uid, :token, :csrf, :access_uid, :access_expiration, :store
|
5
|
+
attr_reader :expiration, :uid, :token, :csrf, :access_uid, :access_expiration, :store, :namespace
|
6
6
|
|
7
|
-
def initialize(csrf,
|
7
|
+
def initialize(csrf,
|
8
|
+
access_uid,
|
9
|
+
access_expiration,
|
10
|
+
store,
|
11
|
+
options = {})
|
8
12
|
@csrf = csrf
|
9
13
|
@access_uid = access_uid
|
10
14
|
@access_expiration = access_expiration
|
11
|
-
@uid = uid
|
12
|
-
@expiration = expiration
|
13
15
|
@store = store
|
14
|
-
@
|
16
|
+
@uid = options.fetch(:uid, SecureRandom.uuid)
|
17
|
+
@expiration = options.fetch(:expiration, JWTSessions.refresh_expiration)
|
18
|
+
@namespace = options.fetch(:namespace, nil)
|
19
|
+
@token = Token.encode(options.fetch(:payload, {}).merge(uid: uid, exp: expiration.to_i))
|
15
20
|
end
|
16
21
|
|
17
22
|
class << self
|
18
|
-
def create(csrf, access_uid, access_expiration, store, payload)
|
19
|
-
inst = new(csrf, access_uid, access_expiration, store, payload)
|
23
|
+
def create(csrf, access_uid, access_expiration, store, payload, namespace)
|
24
|
+
inst = new(csrf, access_uid, access_expiration, store, payload: payload, namespace: namespace)
|
20
25
|
inst.send(:persist_in_store)
|
21
26
|
inst
|
22
27
|
end
|
23
28
|
|
24
|
-
def
|
25
|
-
|
29
|
+
def all(namespace, store)
|
30
|
+
tokens = store.all_in_namespace(namespace)
|
31
|
+
tokens.map do |uid, token_attrs|
|
32
|
+
build_with_token_attrs(store, uid, token_attrs, namespace)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def find(uid, store, namespace)
|
37
|
+
token_attrs = store.fetch_refresh(uid, namespace)
|
26
38
|
raise Errors::Unauthorized, 'Refresh token not found' if token_attrs.empty?
|
39
|
+
build_with_token_attrs(store, uid, token_attrs, namespace)
|
40
|
+
end
|
41
|
+
|
42
|
+
def destroy(uid, store, namespace)
|
43
|
+
store.destroy_refresh(uid, namespace)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def build_with_token_attrs(store, uid, token_attrs, namespace)
|
27
49
|
new(token_attrs[:csrf],
|
28
50
|
token_attrs[:access_uid],
|
29
51
|
token_attrs[:access_expiration],
|
30
52
|
store,
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
def destroy(uid, store)
|
37
|
-
store.destroy_refresh(uid)
|
53
|
+
namespace: namespace,
|
54
|
+
payload: {},
|
55
|
+
uid: uid,
|
56
|
+
expiration: token_attrs[:expiration])
|
38
57
|
end
|
39
58
|
end
|
40
59
|
|
@@ -42,17 +61,17 @@ module JWTSessions
|
|
42
61
|
@csrf = csrf
|
43
62
|
@access_uid = access_uid
|
44
63
|
@access_expiration = access_expiration
|
45
|
-
store.update_refresh(uid, access_uid, access_expiration, csrf)
|
64
|
+
store.update_refresh(uid, access_uid, access_expiration, csrf, namespace)
|
46
65
|
end
|
47
66
|
|
48
67
|
def destroy
|
49
|
-
store.destroy_refresh(uid)
|
68
|
+
store.destroy_refresh(uid, namespace)
|
50
69
|
end
|
51
70
|
|
52
71
|
private
|
53
72
|
|
54
73
|
def persist_in_store
|
55
|
-
store.persist_refresh(uid, access_expiration, access_uid, csrf, expiration)
|
74
|
+
store.persist_refresh(uid, access_expiration, access_uid, csrf, expiration, namespace)
|
56
75
|
end
|
57
76
|
end
|
58
77
|
end
|
data/lib/jwt_sessions/session.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module JWTSessions
|
4
4
|
class Session
|
5
5
|
attr_reader :access_token, :refresh_token, :csrf_token
|
6
|
-
attr_accessor :payload, :store, :refresh_payload
|
6
|
+
attr_accessor :payload, :store, :refresh_payload, :namespace
|
7
7
|
|
8
8
|
def initialize(options = {})
|
9
9
|
@store = options.fetch(:store, JWTSessions.token_store)
|
@@ -11,6 +11,7 @@ module JWTSessions
|
|
11
11
|
@payload = options.fetch(:payload, {})
|
12
12
|
@access_claims = options.fetch(:access_claims, {})
|
13
13
|
@refresh_claims = options.fetch(:refresh_claims, {})
|
14
|
+
@namespace = options.fetch(:namespace, nil)
|
14
15
|
end
|
15
16
|
|
16
17
|
def login
|
@@ -25,6 +26,13 @@ module JWTSessions
|
|
25
26
|
send(:"valid_#{token_type}_csrf?", token, csrf_token)
|
26
27
|
end
|
27
28
|
|
29
|
+
def session_exists?(token, token_type = :access)
|
30
|
+
send(:"#{token_type}_token_data", token)
|
31
|
+
true
|
32
|
+
rescue Errors::Unauthorized
|
33
|
+
false
|
34
|
+
end
|
35
|
+
|
28
36
|
def masked_csrf(access_token)
|
29
37
|
csrf(access_token).token
|
30
38
|
end
|
@@ -34,6 +42,35 @@ module JWTSessions
|
|
34
42
|
refresh_by_uid(&block)
|
35
43
|
end
|
36
44
|
|
45
|
+
def flush_by_token(token)
|
46
|
+
uid = token_uid(token, :refresh, @refresh_claims)
|
47
|
+
flush_by_uid(uid)
|
48
|
+
end
|
49
|
+
|
50
|
+
def flush_by_uid(uid)
|
51
|
+
token = retrieve_refresh_token(uid)
|
52
|
+
|
53
|
+
AccessToken.destroy(token.access_uid, store)
|
54
|
+
token.destroy
|
55
|
+
end
|
56
|
+
|
57
|
+
def flush_namespaced
|
58
|
+
return 0 unless namespace
|
59
|
+
tokens = RefreshToken.all(namespace, store)
|
60
|
+
tokens.each do |token|
|
61
|
+
AccessToken.destroy(token.access_uid, store)
|
62
|
+
token.destroy
|
63
|
+
end.count
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.flush_all(store = JWTSessions.token_store)
|
67
|
+
tokens = RefreshToken.all(nil, store)
|
68
|
+
tokens.each do |token|
|
69
|
+
AccessToken.destroy(token.access_uid, store)
|
70
|
+
token.destroy
|
71
|
+
end.count
|
72
|
+
end
|
73
|
+
|
37
74
|
private
|
38
75
|
|
39
76
|
def valid_access_csrf?(access_token, csrf_token)
|
@@ -52,7 +89,6 @@ module JWTSessions
|
|
52
89
|
|
53
90
|
def csrf(access_token)
|
54
91
|
token_data = access_token_data(access_token)
|
55
|
-
raise Errors::Unauthorized, 'Access token not found' if token_data.empty?
|
56
92
|
CSRFToken.new(token_data[:csrf])
|
57
93
|
end
|
58
94
|
|
@@ -63,7 +99,9 @@ module JWTSessions
|
|
63
99
|
|
64
100
|
def access_token_data(token)
|
65
101
|
uid = token_uid(token, :access, @access_claims)
|
66
|
-
store.fetch_access(uid)
|
102
|
+
data = store.fetch_access(uid)
|
103
|
+
raise Errors::Unauthorized, 'Access token not found' if data.empty?
|
104
|
+
data
|
67
105
|
end
|
68
106
|
|
69
107
|
def refresh_token_data(token)
|
@@ -82,15 +120,17 @@ module JWTSessions
|
|
82
120
|
end
|
83
121
|
|
84
122
|
def retrieve_refresh_token(uid)
|
85
|
-
@_refresh = RefreshToken.find(uid, store)
|
123
|
+
@_refresh = RefreshToken.find(uid, store, namespace)
|
86
124
|
end
|
87
125
|
|
88
126
|
def tokens_hash
|
89
|
-
{
|
127
|
+
{
|
128
|
+
csrf: csrf_token,
|
90
129
|
access: access_token,
|
91
130
|
access_expires_at: Time.at(@_access.expiration.to_i),
|
92
131
|
refresh: refresh_token,
|
93
|
-
refresh_expires_at: Time.at(@_refresh.expiration.to_i)
|
132
|
+
refresh_expires_at: Time.at(@_refresh.expiration.to_i)
|
133
|
+
}
|
94
134
|
end
|
95
135
|
|
96
136
|
def check_refresh_on_time
|
@@ -121,7 +161,8 @@ module JWTSessions
|
|
121
161
|
@_access.uid,
|
122
162
|
@_access.expiration,
|
123
163
|
store,
|
124
|
-
|
164
|
+
refresh_payload,
|
165
|
+
namespace)
|
125
166
|
@refresh_token = @_refresh.token
|
126
167
|
end
|
127
168
|
|
data/lib/jwt_sessions/version.rb
CHANGED
@@ -14,7 +14,8 @@ class TestRefreshToken < Minitest::Test
|
|
14
14
|
@access_uid,
|
15
15
|
JWTSessions.access_expiration - 5,
|
16
16
|
JWTSessions.token_store,
|
17
|
-
{}
|
17
|
+
{},
|
18
|
+
nil)
|
18
19
|
end
|
19
20
|
|
20
21
|
def test_update
|
@@ -27,15 +28,15 @@ class TestRefreshToken < Minitest::Test
|
|
27
28
|
end
|
28
29
|
|
29
30
|
def test_find
|
30
|
-
found_token = JWTSessions::RefreshToken.find(token.uid, JWTSessions.token_store)
|
31
|
+
found_token = JWTSessions::RefreshToken.find(token.uid, JWTSessions.token_store, nil)
|
31
32
|
assert_equal found_token.access_uid, token.access_uid
|
32
33
|
token.destroy
|
33
34
|
end
|
34
35
|
|
35
36
|
def test_destroy
|
36
|
-
JWTSessions::RefreshToken.destroy(token.uid, JWTSessions.token_store)
|
37
|
+
JWTSessions::RefreshToken.destroy(token.uid, JWTSessions.token_store, nil)
|
37
38
|
assert_raises JWTSessions::Errors::Unauthorized do
|
38
|
-
JWTSessions::RefreshToken.find(token.uid, JWTSessions.token_store)
|
39
|
+
JWTSessions::RefreshToken.find(token.uid, JWTSessions.token_store, nil)
|
39
40
|
end
|
40
41
|
end
|
41
42
|
end
|
@@ -14,6 +14,12 @@ class TestSession < Minitest::Test
|
|
14
14
|
@tokens = session.login
|
15
15
|
end
|
16
16
|
|
17
|
+
def teardown
|
18
|
+
redis = Redis.new
|
19
|
+
keys = redis.keys('jwt_*')
|
20
|
+
keys.each { |k| redis.del(k) }
|
21
|
+
end
|
22
|
+
|
17
23
|
def test_login
|
18
24
|
decoded_access = JWTSessions::Token.decode(tokens[:access]).first
|
19
25
|
assert_equal EXPECTED_KEYS, tokens.keys.sort
|
@@ -47,4 +53,62 @@ class TestSession < Minitest::Test
|
|
47
53
|
assert_equal EXPECTED_KEYS, refreshed_tokens.keys.sort
|
48
54
|
assert_equal payload[:test], decoded_access['test']
|
49
55
|
end
|
56
|
+
|
57
|
+
def test_flush_by_token
|
58
|
+
refresh_token = @session.instance_variable_get(:"@_refresh")
|
59
|
+
uid = refresh_token.uid
|
60
|
+
assert_equal refresh_token.token, JWTSessions::RefreshToken.find(uid, JWTSessions.token_store, nil).token
|
61
|
+
|
62
|
+
@session.flush_by_token(refresh_token.token)
|
63
|
+
|
64
|
+
assert_raises JWTSessions::Errors::Unauthorized do
|
65
|
+
JWTSessions::RefreshToken.find(uid, JWTSessions.token_store, nil)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_flush_by_uid
|
70
|
+
refresh_token = @session.instance_variable_get(:"@_refresh")
|
71
|
+
uid = refresh_token.uid
|
72
|
+
|
73
|
+
@session.flush_by_uid(uid)
|
74
|
+
|
75
|
+
assert_raises JWTSessions::Errors::Unauthorized do
|
76
|
+
JWTSessions::RefreshToken.find(uid, JWTSessions.token_store, nil)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_flush_namespaced
|
81
|
+
namespace = 'test_namespace'
|
82
|
+
@session1 = JWTSessions::Session.new(payload: payload, namespace: namespace)
|
83
|
+
@session2 = JWTSessions::Session.new(payload: payload, namespace: namespace)
|
84
|
+
@session1.login
|
85
|
+
@session2.login
|
86
|
+
|
87
|
+
flushed_count = @session1.flush_namespaced
|
88
|
+
|
89
|
+
assert_equal 2, flushed_count
|
90
|
+
assert_raises JWTSessions::Errors::Unauthorized do
|
91
|
+
refresh_token = @session1.instance_variable_get(:"@_refresh")
|
92
|
+
JWTSessions::RefreshToken.find(refresh_token.uid, JWTSessions.token_store, nil)
|
93
|
+
end
|
94
|
+
|
95
|
+
assert_raises JWTSessions::Errors::Unauthorized do
|
96
|
+
refresh_token = @session2.instance_variable_get(:"@_refresh")
|
97
|
+
JWTSessions::RefreshToken.find(refresh_token.uid, JWTSessions.token_store, nil)
|
98
|
+
end
|
99
|
+
|
100
|
+
refresh_token = @session.instance_variable_get(:"@_refresh")
|
101
|
+
flushed_count = @session.flush_namespaced
|
102
|
+
assert_equal 0, flushed_count
|
103
|
+
assert_equal refresh_token.token, JWTSessions::RefreshToken.find(refresh_token.uid, JWTSessions.token_store, nil).token
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_flush_all
|
107
|
+
refresh_token = @session.instance_variable_get(:"@_refresh")
|
108
|
+
flushed_count = JWTSessions::Session.flush_all
|
109
|
+
assert_equal 1, flushed_count
|
110
|
+
assert_raises JWTSessions::Errors::Unauthorized do
|
111
|
+
JWTSessions::RefreshToken.find(refresh_token.uid, JWTSessions.token_store, nil).token
|
112
|
+
end
|
113
|
+
end
|
50
114
|
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: 1.
|
4
|
+
version: 1.2.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-04-
|
11
|
+
date: 2018-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jwt
|