jwt_sessions 1.0.2 → 1.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: 143a1452f628f1d201801cc8b7b4855de56479fb
4
- data.tar.gz: e648fe573c4239e2359d808b5fb93e58d253cf59
3
+ metadata.gz: da93c28c622a3bac51b8f30be0190b0a3c79dda7
4
+ data.tar.gz: 29da1c13c80f4b89572d8f1c3ebe07dd031f775b
5
5
  SHA512:
6
- metadata.gz: d81c0bda06caebed8b38ca9649de98c3e5680859beb7059fd5f0534239f1aeb5b859c0e6f0582bb4585de44b7eef83136fa735d1ac2f7fa6107949e82dd777bb
7
- data.tar.gz: 7e717dc3a0326c81239d1ce12937182bcc5f7d59df884f9eb4e7513f7a398b8c42984b97865e8bdc6f1a3efc75e8b8c96225b04ff76c64adf44f95508cdc57e7
6
+ metadata.gz: 4a21622dd516292d881f87a0b22f140b8dc7c17be838b200cfa7ccbcbb8a1a55a7e7bd075f3ea49982c06811a24fdda721f7625f3b821e4dfeff9583311942a2
7
+ data.tar.gz: b5897c5ef7e0a3be5db1dcc67df71fd0eb56f4a5f3ee5008782c881b006a34e139be045e6a30e7632f5231bf425c62de3b62b150a9e92895befa522802ef346b
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # jwt_sessions
2
2
  [![Gem Version](https://badge.fury.io/rb/jwt_sessions.svg)](https://badge.fury.io/rb/jwt_sessions)
3
3
  [![Maintainability](https://api.codeclimate.com/v1/badges/53de11b8334933b1c0ef/maintainability)](https://codeclimate.com/github/tuwukee/jwt_sessions/maintainability)
4
+ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/c86efdfca81448919ec3e1c1e48fc152)](https://www.codacy.com/app/tuwukee/jwt_sessions?utm_source=github.com&utm_medium=referral&utm_content=tuwukee/jwt_sessions&utm_campaign=Badge_Grade)
4
5
  [![Build Status](https://travis-ci.org/tuwukee/jwt_sessions.svg?branch=master)](https://travis-ci.org/tuwukee/jwt_sessions)
5
6
 
6
7
  XSS/CSRF safe JWT auth designed for SPA
@@ -77,9 +78,18 @@ Specify an encryption key for JSON Web Tokens in `config/initializers/jwt_sessio
77
78
  It's adviced to store the key itself within the app secrets.
78
79
 
79
80
  ```ruby
81
+ JWTSessions.algorithm = 'HS256'
80
82
  JWTSessions.encryption_key = Rails.application.secrets.secret_jwt_encryption_key
81
83
  ```
82
84
 
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 `encryotion_key` to sign the token. For other algorithms you must specify a private and public keys separately.
86
+
87
+ ```ruby
88
+ JWTSessions.algorithm = 'RS256'
89
+ JWTSessions.private_key = OpenSSL::PKey::RSA.generate(2048)
90
+ JWTSessions.public_key = JWTSessions.private_key.public_key
91
+ ```
92
+
83
93
  Generate access/refresh/csrf tokens with a custom payload. \
84
94
  The payload will be available in the controllers once the access (or refresh) token is authorized. \
85
95
  Access/refresh tokens contain expiration time in their payload. Yet expiration times are also added to the output just in case.
@@ -290,9 +300,46 @@ JWTSessions.algorithm = 'HS256'
290
300
  You need to specify a secret to use for HMAC, this setting doesn't have a default value.
291
301
 
292
302
  ```ruby
293
- JWTSessions.secret = 'secret'
303
+ JWTSessions.encryption_key = 'secret'
304
+ ```
305
+
306
+ If you are using another algorithm like RSA/ECDSA/EDDSA you should specify private and public keys.
307
+
308
+ ```ruby
309
+ JWTSessions.private_key = 'abcd'
310
+ JWTSessions.public_key = 'efjh'
311
+ ```
312
+
313
+ NOTE: ED25519 and HS512256 require rbnacl installation in order to make it work.
314
+
315
+ jwt_sessions only uses `exp` claim by default when it decodes tokens, you can specify which additional claims to use by
316
+ setting `jwt_options`. You can also specify leeway to account for clock skew.
317
+
318
+ ```ruby
319
+ JWTSessions.jwt_options.verify_iss = true
320
+ JWTSessions.jwt_options.verify_sub = true
321
+ JWTSessions.jwt_options.verify_iat = true
322
+ JWTSessions.jwt_options.verify_aud = true
323
+ JWTSessions.jwt_options.leeway = 30 # seconds
294
324
  ```
295
325
 
326
+ To pass options like `sub`, `aud`, `iss`, or leeways you should specify a method called `token_claims` in your controller.
327
+
328
+ ```ruby
329
+ class UsersController < ApplicationController
330
+ before_action :authorize_access_request!
331
+
332
+ def token_claims
333
+ {
334
+ aud: ['admin', 'staff'],
335
+ exp_leeway: 15 # will be used instead of default leeway only for exp claim
336
+ }
337
+ end
338
+ end
339
+ ```
340
+
341
+ Claims are also supported by `JWTSessions::Session`, you can pass `access_claims` and `refresh_claims` options in the initializer
342
+
296
343
  ##### Request headers and cookies names
297
344
 
298
345
  Default request headers/cookies names can be re-configured
@@ -307,7 +354,7 @@ JWTSessions.csrf_header = 'X-CSRF-Token'
307
354
 
308
355
  ##### Expiration time
309
356
 
310
- Acces token must have a short life span, while refresh tokens can be stored for a longer time period
357
+ Access token must have a short life span, while refresh tokens can be stored for a longer time period
311
358
 
312
359
  ```ruby
313
360
  JWTSessions.access_exp_time = 3600 # 1 hour in seconds
@@ -341,17 +388,14 @@ session.refresh(refresh_token) { |refresh_token_uid, access_token_expiration| ..
341
388
 
342
389
  ## TODO
343
390
 
344
- Ability to specify public and private keys for RSA/EDCSA/EDDSA, there are no default values for keys. \
345
- You can use instructions from [ruby-jwt](https://github.com/jwt/ruby-jwt) to generate keys corresponding keys.
346
-
347
- ```ruby
348
- JWTSessions.private_key = 'private_key'
349
- JWTSessions.public_key = 'public_key_for_private'
350
- ```
391
+ Session cleanup by uid or refresh token instance. \
392
+ Refresh token namespaces to allow centralized token cleanup per namespace (scenarios like password reset). \
393
+ Documentation for code.
351
394
 
352
395
  ## Contributing
353
396
 
354
- Fork & Pull Request
397
+ Fork & Pull Request \
398
+ RbNaCl and sodium cryptographic library are required for tests
355
399
 
356
400
  ## License
357
401
 
@@ -14,7 +14,8 @@ module JWTSessions
14
14
  rescue Errors::Unauthorized
15
15
  cookie_based_auth(token_type)
16
16
  end
17
- invalid_authorization unless Token.valid_payload?(payload)
17
+ # triggers token decode and jwt claim checks
18
+ payload
18
19
  check_csrf(token_type)
19
20
  end
20
21
  end
@@ -83,7 +84,8 @@ module JWTSessions
83
84
  end
84
85
 
85
86
  def payload
86
- @_payload ||= Token.decode(found_token).first
87
+ claims = respond_to?(:token_claims) ? token_claims : {}
88
+ @_payload ||= Token.decode(found_token, claims).first
87
89
  end
88
90
  end
89
91
  end
@@ -9,6 +9,8 @@ module JWTSessions
9
9
  @store = options.fetch(:store, JWTSessions.token_store)
10
10
  @refresh_payload = options.fetch(:refresh_payload, {})
11
11
  @payload = options.fetch(:payload, {})
12
+ @access_claims = options.fetch(:access_claims, {})
13
+ @refresh_claims = options.fetch(:refresh_claims, {})
12
14
  end
13
15
 
14
16
  def login
@@ -60,17 +62,17 @@ module JWTSessions
60
62
  end
61
63
 
62
64
  def access_token_data(token)
63
- uid = token_uid(token, :access)
65
+ uid = token_uid(token, :access, @access_claims)
64
66
  store.fetch_access(uid)
65
67
  end
66
68
 
67
69
  def refresh_token_data(token)
68
- uid = token_uid(token, :refresh)
70
+ uid = token_uid(token, :refresh, @refresh_claims)
69
71
  retrieve_refresh_token(uid)
70
72
  end
71
73
 
72
- def token_uid(token, type)
73
- token_payload = JWTSessions::Token.decode(token).first
74
+ def token_uid(token, type, claims)
75
+ token_payload = JWTSessions::Token.decode(token, claims).first
74
76
  uid = token_payload.fetch('uid', nil)
75
77
  if uid.nil?
76
78
  message = "#{type.to_s.capitalize} token payload does not contain token uid"
@@ -7,30 +7,21 @@ module JWTSessions
7
7
  class << self
8
8
  def encode(payload)
9
9
  exp_payload = meta.merge(payload)
10
- JWT.encode(exp_payload, JWTSessions.encryption_key, JWTSessions.algorithm)
10
+ JWT.encode(exp_payload, JWTSessions.private_key, JWTSessions.algorithm)
11
11
  end
12
12
 
13
- def decode(token)
14
- JWT.decode(token, JWTSessions.encryption_key, true, { algorithm: JWTSessions.algorithm, verify_expiration: false })
13
+ def decode(token, claims = {})
14
+ decode_options = { algorithm: JWTSessions.algorithm }.merge(JWTSessions.jwt_options.to_h).merge(claims)
15
+ JWT.decode(token, JWTSessions.public_key, JWTSessions.validate?, decode_options)
15
16
  rescue JWT::DecodeError => e
16
17
  raise Errors::Unauthorized, e.message
17
18
  rescue StandardError
18
19
  raise Errors::Unauthorized, 'could not decode a token'
19
20
  end
20
21
 
21
- def valid_payload?(payload)
22
- !expired?(payload)
23
- end
24
-
25
22
  def meta
26
23
  { exp: JWTSessions.access_expiration }
27
24
  end
28
-
29
- def expired?(payload)
30
- Time.at(payload['exp']) < Time.now
31
- rescue StandardError
32
- raise Errors::Unauthorized, 'invalid payload expiration time'
33
- end
34
25
  end
35
26
  end
36
27
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JWTSessions
4
- VERSION = '1.0.2'
4
+ VERSION = '1.1.0'
5
5
  end
data/lib/jwt_sessions.rb CHANGED
@@ -18,6 +18,10 @@ module JWTSessions
18
18
 
19
19
  attr_writer :token_store
20
20
 
21
+ NONE = 'none'
22
+
23
+ JWTOptions = Struct.new(*JWT::DefaultOptions::DEFAULT_OPTIONS.keys)
24
+
21
25
  DEFAULT_SETTINGS_KEYS = %i[access_cookie
22
26
  access_exp_time
23
27
  access_header
@@ -30,19 +34,19 @@ module JWTSessions
30
34
  refresh_exp_time
31
35
  refresh_header
32
36
  token_prefix].freeze
33
- DEFAULT_REDIS_HOST = '127.0.0.1'
34
- DEFAULT_REDIS_PORT = '6379'
35
- DEFAULT_REDIS_DB_NAME = 'jwtokens'
36
- DEFAULT_TOKEN_PREFIX = 'jwt_'
37
- DEFAULT_ALGORITHM = 'HS256'
38
- DEFAULT_ACCESS_EXP_TIME = 3600 # 1 hour in seconds
39
- DEFAULT_REFRESH_EXP_TIME = 604800 # 1 week in seconds
40
- DEFAULT_ACCESS_COOKIE = 'jwt_access'
41
- DEFAULT_ACCESS_HEADER = 'Authorization'
42
- DEFAULT_REFRESH_COOKIE = 'jwt_refresh'
43
- DEFAULT_REFRESH_HEADER = 'X-Refresh-Token'
44
- DEFAULT_CSRF_HEADER = 'X-CSRF-Token'
45
37
 
38
+ DEFAULT_REDIS_HOST = '127.0.0.1'
39
+ DEFAULT_REDIS_PORT = '6379'
40
+ DEFAULT_REDIS_DB_NAME = 'jwtokens'
41
+ DEFAULT_TOKEN_PREFIX = 'jwt_'
42
+ DEFAULT_ALGORITHM = 'HS256'
43
+ DEFAULT_ACCESS_EXP_TIME = 3600 # 1 hour in seconds
44
+ DEFAULT_REFRESH_EXP_TIME = 604800 # 1 week in seconds
45
+ DEFAULT_ACCESS_COOKIE = 'jwt_access'
46
+ DEFAULT_ACCESS_HEADER = 'Authorization'
47
+ DEFAULT_REFRESH_COOKIE = 'jwt_refresh'
48
+ DEFAULT_REFRESH_HEADER = 'X-Refresh-Token'
49
+ DEFAULT_CSRF_HEADER = 'X-CSRF-Token'
46
50
 
47
51
  DEFAULT_SETTINGS_KEYS.each do |setting|
48
52
  var_name = :"@#{setting}"
@@ -61,13 +65,41 @@ module JWTSessions
61
65
  end
62
66
  end
63
67
 
68
+ def jwt_options
69
+ @jwt_options ||= JWTOptions.new(*JWT::DefaultOptions::DEFAULT_OPTIONS.values)
70
+ end
71
+
72
+ def algorithm=(algo)
73
+ raise Errors::Malconfigured, "algorithm #{algo} is not supported" unless supported_algos.include?(algo)
74
+ @algorithm = algo
75
+ end
76
+
64
77
  def token_store
65
78
  RedisTokenStore.instance(redis_host, redis_port, redis_db_name, token_prefix)
66
79
  end
67
80
 
68
- def encryption_key
69
- raise Errors::Malconfigured, 'encryption_key is not specified' unless @encryption_key
70
- @encryption_key
81
+ def validate?
82
+ algorithm != NONE
83
+ end
84
+
85
+ [:public_key, :private_key].each do |key|
86
+ var_name = :"@#{key}"
87
+ define_method("#{key}") do
88
+ return nil if algorithm == NONE
89
+ var = instance_variable_get(var_name)
90
+ raise Errors::Malconfigured, "#{key} is not specified" unless var
91
+ var
92
+ end
93
+
94
+ define_method("#{key}=") do |val|
95
+ instance_variable_set(var_name, val)
96
+ end
97
+ end
98
+
99
+ # should be used for hmac only
100
+ def encryption_key=(key)
101
+ @public_key = key
102
+ @private_key = key
71
103
  end
72
104
 
73
105
  def access_expiration
@@ -78,9 +110,6 @@ module JWTSessions
78
110
  Time.now.to_i + refresh_exp_time.to_i
79
111
  end
80
112
 
81
- def encryption_key=(key)
82
- @encryption_key = key
83
- end
84
113
 
85
114
  def header_by(token_type)
86
115
  send("#{token_type}_header")
@@ -89,4 +118,12 @@ module JWTSessions
89
118
  def cookie_by(token_type)
90
119
  send("#{token_type}_cookie")
91
120
  end
121
+
122
+ private
123
+
124
+ def supported_algos
125
+ # TODO once ECDSA is fixed in ruby-jwt it can be added to the list of algos just the same way others are added
126
+ algos = JWT::Algos.constants - [:Unsupported, :Ecdsa]
127
+ algos.map { |algo| JWT::Algos.const_get(algo)::SUPPORTED }.flatten + [NONE, *JWT::Algos::Ecdsa::SUPPORTED.split(' ')]
128
+ end
92
129
  end
@@ -39,10 +39,10 @@ class TestSession < Minitest::Test
39
39
  JWTSessions.access_exp_time = 0
40
40
  @session = JWTSessions::Session.new(payload: payload)
41
41
  @tokens = session.login
42
+ JWTSessions.access_exp_time = 3600
42
43
  refreshed_tokens = session.refresh(tokens[:refresh]) do
43
44
  raise JWTSessions::Errors::Unauthorized
44
45
  end
45
- JWTSessions.access_exp_time = 3600
46
46
  decoded_access = JWTSessions::Token.decode(refreshed_tokens[:access]).first
47
47
  assert_equal EXPECTED_KEYS, refreshed_tokens.keys.sort
48
48
  assert_equal payload[:test], decoded_access['test']
@@ -2,17 +2,128 @@
2
2
 
3
3
  require 'minitest/autorun'
4
4
  require 'jwt_sessions'
5
+ require 'pry'
6
+
7
+ nacl_supported_versions = {
8
+ 'ruby' => ['~> 2.2.6', '~> 2.3.0', '~> 2.4.2'],
9
+ 'jruby' => ['~> 9.1.6.0']
10
+ }.each_with_object([]) do |(platform, versions), acc|
11
+ acc.concat(versions.map { |version| Gem::Dependency.new(platform, version) })
12
+ end
13
+
14
+ nacl_supported = nacl_supported_versions.any? { |version| version.match?(RUBY_ENGINE, RUBY_VERSION) }
15
+
16
+ $uses_nacl = !!(defined?(RbNaCl) || require('rbnacl') if nacl_supported)
5
17
 
6
18
  class TestToken < Minitest::Test
7
19
  attr_reader :payload
8
20
 
9
21
  def setup
10
- JWTSessions.encryption_key = 'super secret'
11
22
  @payload = { 'user_id' => 1, 'secret' => 'mystery' }
23
+ JWTSessions.encryption_key = 'abcdefghijklmnopqrstuvwxyzABCDEF'
24
+ end
25
+
26
+ def teardown
27
+ JWTSessions.algorithm = JWTSessions::DEFAULT_ALGORITHM
28
+ JWTSessions.instance_variable_set(:'@jwt_options', JWTSessions::JWTOptions.new(*JWT::DefaultOptions::DEFAULT_OPTIONS.values))
29
+ end
30
+
31
+ def test_rsa_token_decode
32
+ JWTSessions.algorithm = 'RS256'
33
+ JWTSessions.private_key = OpenSSL::PKey::RSA.generate 2048
34
+ JWTSessions.public_key = JWTSessions.private_key.public_key
35
+
36
+ token = JWTSessions::Token.encode(payload)
37
+ decoded = JWTSessions::Token.decode(token).first
38
+ assert_equal payload['user_id'], decoded['user_id']
39
+ assert_equal payload['secret'], decoded['secret']
40
+ end
41
+
42
+ def test_eddsa_token_decode
43
+ skip unless $uses_nacl
44
+ JWTSessions.algorithm = 'ED25519'
45
+ JWTSessions.private_key = ::RbNaCl::Signatures::Ed25519::SigningKey.new('abcdefghijklmnopqrstuvwxyzABCDEF')
46
+ JWTSessions.public_key = JWTSessions.private_key.verify_key
47
+
48
+ token = JWTSessions::Token.encode(payload)
49
+ decoded = JWTSessions::Token.decode(token).first
50
+ assert_equal payload['user_id'], decoded['user_id']
51
+ assert_equal payload['secret'], decoded['secret']
52
+ end
53
+
54
+ def test_ecdsa_token_decode
55
+ JWTSessions.algorithm = 'ES256'
56
+ JWTSessions.private_key = OpenSSL::PKey::EC.new 'prime256v1'
57
+ JWTSessions.private_key.generate_key
58
+ JWTSessions.public_key = OpenSSL::PKey::EC.new JWTSessions.private_key
59
+ JWTSessions.public_key.private_key = nil
60
+
61
+ token = JWTSessions::Token.encode(payload)
62
+ decoded = JWTSessions::Token.decode(token).first
63
+ assert_equal payload['user_id'], decoded['user_id']
64
+ assert_equal payload['secret'], decoded['secret']
65
+ end
66
+
67
+ def test_hmac_token_decode
68
+ JWTSessions.encryption_key = 'abcdefghijklmnopqrstuvwxyzABCDEF'
69
+ token = JWTSessions::Token.encode(payload)
70
+ decoded = JWTSessions::Token.decode(token).first
71
+ assert_equal payload['user_id'], decoded['user_id']
72
+ assert_equal payload['secret'], decoded['secret']
73
+ end
74
+
75
+ def test_token_sub_claim
76
+ JWTSessions.encryption_key = 'abcdefghijklmnopqrstuvwxyzABCDEF'
77
+ JWTSessions.jwt_options.verify_sub = true
78
+ token = JWTSessions::Token.encode(payload.merge(sub: 'subject'))
79
+ decoded = JWTSessions::Token.decode(token, { sub: 'subject' }).first
80
+ assert_equal payload['user_id'], decoded['user_id']
81
+ assert_equal payload['secret'], decoded['secret']
82
+ assert_raises JWTSessions::Errors::Unauthorized do
83
+ JWTSessions::Token.decode(token, { sub: 'different subject' })
84
+ end
85
+ end
86
+
87
+ def test_token_iss_claim
88
+ JWTSessions.encryption_key = 'abcdefghijklmnopqrstuvwxyzABCDEF'
89
+ JWTSessions.jwt_options.verify_iss = true
90
+ token = JWTSessions::Token.encode(payload.merge(iss: 'Me'))
91
+ decoded = JWTSessions::Token.decode(token, { iss: 'Me' }).first
92
+ assert_equal payload['user_id'], decoded['user_id']
93
+ assert_equal payload['secret'], decoded['secret']
94
+ assert_raises JWTSessions::Errors::Unauthorized do
95
+ JWTSessions::Token.decode(token, { iss: 'Not Me' })
96
+ end
97
+ end
98
+
99
+ def test_token_aud_claim
100
+ JWTSessions.encryption_key = 'abcdefghijklmnopqrstuvwxyzABCDEF'
101
+ JWTSessions.jwt_options.verify_aud = true
102
+ token = JWTSessions::Token.encode(payload.merge(aud: ['young', 'old']))
103
+ decoded = JWTSessions::Token.decode(token, { aud: ['young'] }).first
104
+ assert_equal payload['user_id'], decoded['user_id']
105
+ assert_equal payload['secret'], decoded['secret']
106
+ assert_raises JWTSessions::Errors::Unauthorized do
107
+ JWTSessions::Token.decode(token, { aud: ['adult'] })
108
+ end
109
+ end
110
+
111
+ def test_token_leeway_decode
112
+ JWTSessions.encryption_key = 'abcdefghijklmnopqrstuvwxyzABCDEF'
113
+ JWTSessions.jwt_options.leeway = 50
114
+ token = JWTSessions::Token.encode(payload.merge(exp: Time.now.to_i - 20))
115
+ decoded = JWTSessions::Token.decode(token).first
116
+ assert_equal payload['user_id'], decoded['user_id']
117
+ assert_equal payload['secret'], decoded['secret']
118
+ token = JWTSessions::Token.encode(payload.merge(exp: Time.now.to_i - 100))
119
+ assert_raises JWTSessions::Errors::Unauthorized do
120
+ JWTSessions::Token.decode(token)
121
+ end
12
122
  end
13
123
 
14
- def test_valid_token_decode
15
- token = JWTSessions::Token.encode(payload)
124
+ def test_none_token_decode
125
+ JWTSessions.algorithm = JWTSessions::NONE
126
+ token = JWTSessions::Token.encode(payload)
16
127
  decoded = JWTSessions::Token.decode(token).first
17
128
  assert_equal payload['user_id'], decoded['user_id']
18
129
  assert_equal payload['secret'], decoded['secret']
@@ -31,12 +142,9 @@ class TestToken < Minitest::Test
31
142
  end
32
143
 
33
144
  def test_payload_exp_time
145
+ token = JWTSessions::Token.encode(payload.merge(exp: Time.now.to_i - (3600 * 24)))
34
146
  assert_raises JWTSessions::Errors::Unauthorized do
35
- JWTSessions::Token.valid_payload?(payload)
147
+ JWTSessions::Token.decode(token)
36
148
  end
37
- payload['exp'] = Time.now - (3600 * 24)
38
- assert_equal false, JWTSessions::Token.valid_payload?(payload)
39
- payload['exp'] = Time.now + (3600 * 24)
40
- assert_equal true, JWTSessions::Token.valid_payload?(payload)
41
149
  end
42
150
  end
@@ -21,7 +21,11 @@ class TestJWTSessions < Minitest::Test
21
21
  def test_encryption_key
22
22
  JWTSessions.encryption_key = nil
23
23
  assert_raises JWTSessions::Errors::Malconfigured do
24
- JWTSessions.encryption_key
24
+ JWTSessions.private_key
25
+ end
26
+
27
+ assert_raises JWTSessions::Errors::Malconfigured do
28
+ JWTSessions.public_key
25
29
  end
26
30
  end
27
31
 
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jwt_sessions
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.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-04-19 00:00:00.000000000 Z
11
+ date: 2018-04-21 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: '1.4'
19
+ version: '2.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.4'
26
+ version: '2.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: redis
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '10.0'
89
+ version: '12.3'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '10.0'
96
+ version: '12.3'
97
97
  description: XSS/CSRF safe JWT auth designed for SPA
98
98
  email: yulia.oletskaya@gmail.com
99
99
  executables: []