slosilo 1.1.0 → 2.2.2

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.
@@ -1,25 +1,40 @@
1
1
  module Slosilo
2
2
  class Symmetric
3
+ VERSION_MAGIC = 'G'
4
+ TAG_LENGTH = 16
5
+
3
6
  def initialize
4
- @cipher = OpenSSL::Cipher.new 'AES-256-CBC'
7
+ @cipher = OpenSSL::Cipher.new 'aes-256-gcm' # NB: has to be lower case for whatever reason.
5
8
  end
6
-
9
+
10
+ # This lets us do a final sanity check in migrations from older encryption versions
11
+ def cipher_name
12
+ @cipher.name
13
+ end
14
+
7
15
  def encrypt plaintext, opts = {}
8
16
  @cipher.reset
9
17
  @cipher.encrypt
10
- @cipher.key = opts[:key]
18
+ @cipher.key = (opts[:key] or raise("missing :key option"))
11
19
  @cipher.iv = iv = random_iv
12
- ctxt = @cipher.update(plaintext)
13
- iv + ctxt + @cipher.final
20
+ @cipher.auth_data = opts[:aad] || "" # Nothing good happens if you set this to nil, or don't set it at all
21
+ ctext = @cipher.update(plaintext) + @cipher.final
22
+ tag = @cipher.auth_tag(TAG_LENGTH)
23
+ "#{VERSION_MAGIC}#{tag}#{iv}#{ctext}"
14
24
  end
15
-
25
+
16
26
  def decrypt ciphertext, opts = {}
27
+ version, tag, iv, ctext = unpack ciphertext
28
+
29
+ raise "Invalid version magic: expected #{VERSION_MAGIC} but was #{version}" unless version == VERSION_MAGIC
30
+
17
31
  @cipher.reset
18
32
  @cipher.decrypt
19
33
  @cipher.key = opts[:key]
20
- @cipher.iv, ctxt = ciphertext.unpack("a#{@cipher.iv_len}a*")
21
- ptxt = @cipher.update(ctxt)
22
- ptxt + @cipher.final
34
+ @cipher.iv = iv
35
+ @cipher.auth_tag = tag
36
+ @cipher.auth_data = opts[:aad] || ""
37
+ @cipher.update(ctext) + @cipher.final
23
38
  end
24
39
 
25
40
  def random_iv
@@ -29,5 +44,11 @@ module Slosilo
29
44
  def random_key
30
45
  @cipher.random_key
31
46
  end
47
+
48
+ private
49
+ # return tag, iv, ctext
50
+ def unpack msg
51
+ msg.unpack "aa#{TAG_LENGTH}a#{@cipher.iv_len}a*"
52
+ end
32
53
  end
33
54
  end
@@ -1,3 +1,3 @@
1
1
  module Slosilo
2
- VERSION = "1.1.0"
2
+ VERSION = "2.2.2"
3
3
  end
@@ -24,4 +24,9 @@ namespace :slosilo do
24
24
  task :migrate => :environment do |t|
25
25
  Slosilo.adapter.migrate!
26
26
  end
27
+
28
+ desc "Recalculate fingerprints in keystore"
29
+ task :recalculate_fingerprints => :environment do |t|
30
+ Slosilo.adapter.recalculate_fingerprints
31
+ end
27
32
  end
@@ -0,0 +1,11 @@
1
+ #!/bin/bash -e
2
+
3
+ docker pull registry.tld/conjurinc/publish-rubygem
4
+
5
+ docker run -i --rm -v $PWD:/src -w /src alpine/git clean -fxd
6
+
7
+ summon --yaml "RUBYGEMS_API_KEY: !var rubygems/api-key" \
8
+ docker run --rm --env-file @SUMMONENVFILE -v "$(pwd)":/opt/src \
9
+ registry.tld/conjurinc/publish-rubygem slosilo
10
+
11
+ docker run -i --rm -v $PWD:/src -w /src alpine/git clean -fxd
@@ -1,5 +1,12 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/slosilo/version', __FILE__)
2
+ begin
3
+ require File.expand_path('../lib/slosilo/version', __FILE__)
4
+ rescue LoadError
5
+ # so that bundle can be run without the app code
6
+ module Slosilo
7
+ VERSION = '0.0.0'
8
+ end
9
+ end
3
10
 
4
11
  Gem::Specification.new do |gem|
5
12
  gem.authors = ["Rafa\305\202 Rzepecki"]
@@ -16,12 +23,14 @@ Gem::Specification.new do |gem|
16
23
  gem.require_paths = ["lib"]
17
24
  gem.version = Slosilo::VERSION
18
25
  gem.required_ruby_version = '>= 1.9.3'
19
-
26
+
20
27
  gem.add_development_dependency 'rake'
21
28
  gem.add_development_dependency 'rspec', '~> 3.0'
22
29
  gem.add_development_dependency 'ci_reporter_rspec'
23
30
  gem.add_development_dependency 'simplecov'
31
+ gem.add_development_dependency 'simplecov-cobertura'
24
32
  gem.add_development_dependency 'io-grab', '~> 0.0.1'
25
33
  gem.add_development_dependency 'sequel' # for sequel tests
26
34
  gem.add_development_dependency 'sqlite3' # for sequel tests
35
+ gem.add_development_dependency 'activesupport' # for convenience in specs
27
36
  end
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+ require 'slosilo/attr_encrypted'
3
+
4
+ describe Slosilo::EncryptedAttributes do
5
+ before(:all) do
6
+ Slosilo::encryption_key = OpenSSL::Cipher.new("aes-256-gcm").random_key
7
+ end
8
+
9
+ let(:aad) { proc{ |_| "hithere" } }
10
+
11
+ let(:base){
12
+ Class.new do
13
+ attr_accessor :normal_ivar,:with_aad
14
+ def stupid_ivar
15
+ side_effect!
16
+ @_explicit
17
+ end
18
+ def stupid_ivar= e
19
+ side_effect!
20
+ @_explicit = e
21
+ end
22
+ def side_effect!
23
+
24
+ end
25
+ end
26
+ }
27
+
28
+ let(:sub){
29
+ Class.new(base) do
30
+ attr_encrypted :normal_ivar, :stupid_ivar
31
+ end
32
+ }
33
+
34
+ subject{ sub.new }
35
+
36
+ context "when setting a normal ivar" do
37
+ let(:value){ "some value" }
38
+ it "stores an encrypted value in the ivar" do
39
+ subject.normal_ivar = value
40
+ expect(subject.instance_variable_get(:"@normal_ivar")).to_not eq(value)
41
+ end
42
+
43
+ it "recovers the value set" do
44
+ subject.normal_ivar = value
45
+ expect(subject.normal_ivar).to eq(value)
46
+ end
47
+ end
48
+
49
+ context "when setting an attribute with an implementation" do
50
+ it "calls the base class method" do
51
+ expect(subject).to receive_messages(:side_effect! => nil)
52
+ subject.stupid_ivar = "hi"
53
+ expect(subject.stupid_ivar).to eq("hi")
54
+ end
55
+ end
56
+
57
+ context "when given an :aad option" do
58
+
59
+ let(:cipher){ Slosilo::EncryptedAttributes.cipher }
60
+ let(:key){ Slosilo::EncryptedAttributes.key}
61
+ context "that is a string" do
62
+ let(:aad){ "hello there" }
63
+ before{ sub.attr_encrypted :with_aad, aad: aad }
64
+ it "encrypts the value with the given string for auth data" do
65
+ expect(cipher).to receive(:encrypt).with("hello", key: key, aad: aad)
66
+ subject.with_aad = "hello"
67
+ end
68
+
69
+ it "decrypts the encrypted value" do
70
+ subject.with_aad = "foo"
71
+ expect(subject.with_aad).to eq("foo")
72
+ end
73
+ end
74
+
75
+ context "that is nil" do
76
+ let(:aad){ nil }
77
+ before{ sub.attr_encrypted :with_aad, aad: aad }
78
+ it "encrypts the value with an empty string for auth data" do
79
+ expect(cipher).to receive(:encrypt).with("hello",key: key, aad: "").and_call_original
80
+ subject.with_aad = "hello"
81
+ end
82
+
83
+ it "decrypts the encrypted value" do
84
+ subject.with_aad = "hello"
85
+ expect(subject.with_aad).to eq("hello")
86
+ end
87
+ end
88
+
89
+ context "that is a proc" do
90
+ let(:aad){
91
+ proc{ |o| "x" }
92
+ }
93
+
94
+ before{ sub.attr_encrypted :with_aad, aad: aad }
95
+
96
+ it "calls the proc with the object being encrypted" do
97
+ expect(aad).to receive(:[]).with(subject).and_call_original
98
+ subject.with_aad = "hi"
99
+ end
100
+
101
+ it "encrypts the value with the string returned for auth data" do
102
+ expect(cipher).to receive(:encrypt).with("hello", key: key, aad: aad[subject]).and_call_original
103
+ subject.with_aad = "hello"
104
+ end
105
+ it "decrypts the encrypted value" do
106
+ subject.with_aad = "hello"
107
+ expect(subject.with_aad).to eq("hello")
108
+ end
109
+ end
110
+
111
+ end
112
+
113
+
114
+ end
@@ -22,7 +22,7 @@ describe Slosilo::Adapters::FileAdapter do
22
22
  context "unacceptable id" do
23
23
  let(:id) { "foo.bar" }
24
24
  it "isn't accepted" do
25
- expect { subject.put_key id, key }.to raise_error
25
+ expect { subject.put_key id, key }.to raise_error /id should not contain a period/
26
26
  end
27
27
  end
28
28
  context "acceptable id" do
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ # (Mostly) integration tests for JWT token format
4
+ describe Slosilo::Key do
5
+ include_context "with example key"
6
+
7
+ describe '#issue_jwt' do
8
+ it 'issues an JWT token with given claims' do
9
+ allow(Time).to receive(:now) { DateTime.parse('2014-06-04 23:22:32 -0400').to_time }
10
+
11
+ tok = key.issue_jwt sub: 'host/example', cidr: %w(fec0::/64)
12
+
13
+ expect(tok).to be_frozen
14
+
15
+ expect(tok.header).to eq \
16
+ alg: 'conjur.org/slosilo/v2',
17
+ kid: key_fingerprint
18
+ expect(tok.claims).to eq \
19
+ iat: 1401938552,
20
+ sub: 'host/example',
21
+ cidr: ['fec0::/64']
22
+
23
+ expect(key.verify_signature tok.string_to_sign, tok.signature).to be_truthy
24
+ end
25
+ end
26
+ end
27
+
28
+ describe Slosilo::JWT do
29
+ context "with a signed token" do
30
+ let(:signature) { 'very signed, such alg' }
31
+ subject(:token) { Slosilo::JWT.new test: "token" }
32
+ before do
33
+ allow(Time).to receive(:now) { DateTime.parse('2014-06-04 23:22:32 -0400').to_time }
34
+ token.add_signature(alg: 'test-sig') { signature }
35
+ end
36
+
37
+ it 'allows conversion to JSON representation with #to_json' do
38
+ json = JSON.load token.to_json
39
+ expect(JSON.load Base64.urlsafe_decode64 json['protected']).to eq \
40
+ 'alg' => 'test-sig'
41
+ expect(JSON.load Base64.urlsafe_decode64 json['payload']).to eq \
42
+ 'iat' => 1401938552, 'test' => 'token'
43
+ expect(Base64.urlsafe_decode64 json['signature']).to eq signature
44
+ end
45
+
46
+ it 'allows conversion to compact representation with #to_s' do
47
+ h, c, s = token.to_s.split '.'
48
+ expect(JSON.load Base64.urlsafe_decode64 h).to eq \
49
+ 'alg' => 'test-sig'
50
+ expect(JSON.load Base64.urlsafe_decode64 c).to eq \
51
+ 'iat' => 1401938552, 'test' => 'token'
52
+ expect(Base64.urlsafe_decode64 s).to eq signature
53
+ end
54
+ end
55
+
56
+ describe '#to_json' do
57
+ it "passes any parameters" do
58
+ token = Slosilo::JWT.new
59
+ allow(token).to receive_messages \
60
+ header: :header,
61
+ claims: :claims,
62
+ signature: :signature
63
+ expect_any_instance_of(Hash).to receive(:to_json).with :testing
64
+ expect(token.to_json :testing)
65
+ end
66
+ end
67
+
68
+ describe '()' do
69
+ include_context "with example key"
70
+
71
+ it 'understands both serializations' do
72
+ [COMPACT_TOKEN, JSON_TOKEN].each do |token|
73
+ token = Slosilo::JWT token
74
+ expect(token.header).to eq \
75
+ 'typ' => 'JWT',
76
+ 'alg' => 'conjur.org/slosilo/v2',
77
+ 'kid' => key_fingerprint
78
+ expect(token.claims).to eq \
79
+ 'sub' => 'host/example',
80
+ 'iat' => 1401938552,
81
+ 'exp' => 1401938552 + 60*60,
82
+ 'cidr' => ['fec0::/64']
83
+ expect(key.verify_signature token.string_to_sign, token.signature).to be_truthy
84
+ end
85
+ end
86
+
87
+ it 'is a noop if already parsed' do
88
+ token = Slosilo::JWT COMPACT_TOKEN
89
+ expect(Slosilo::JWT token).to eq token
90
+ end
91
+
92
+ it 'raises ArgumentError on failure to convert' do
93
+ expect { Slosilo::JWT "foo bar" }.to raise_error ArgumentError
94
+ expect { Slosilo::JWT elite: 31337 }.to raise_error ArgumentError
95
+ expect { Slosilo::JWT "foo.bar.xyzzy" }.to raise_error ArgumentError
96
+ end
97
+ end
98
+
99
+ COMPACT_TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJjb25qdXIub3JnL3Nsb3NpbG8vdjIiLCJraWQiOiIxMDdiZGI4NTAxYzQxOWZhZDJmZGIyMGI0NjdkNGQwYTYyYTE2YTk4YzM1ZjJkYTBlYjNiMWZmOTI5Nzk1YWQ5In0=.eyJzdWIiOiJob3N0L2V4YW1wbGUiLCJjaWRyIjpbImZlYzA6Oi82NCJdLCJleHAiOjE0MDE5NDIxNTIsImlhdCI6MTQwMTkzODU1Mn0=.qSxy6gx0DbiIc-Wz_vZhBsYi1SCkHhzxfMGPnnG6MTqjlzy7ntmlU2H92GKGoqCRo6AaNLA_C3hA42PeEarV5nMoTj8XJO_kwhrt2Db2OX4u83VS0_enoztWEZG5s45V0Lv71lVR530j4LD-hpqhm_f4VuISkeH84u0zX7s1zKOlniuZP-abCAHh0htTnrVz9wKG0VywkCUmWYyNNqC2h8PRf64SvCWcQ6VleHpjO-ms8OeTw4ZzRbzKMi0mL6eTmQlbT3PeBArUaS0pNJPg9zdDQaL2XDOofvQmj6Yy_8RA4eCt9HEfTYEdriVqK-_9QCspbGzFVn9GTWf51MRi5dngV9ItsDoG9ktDtqFuMttv7TcqjftsIHZXZsAZ175E".freeze
100
+
101
+ JSON_TOKEN = "{\"protected\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJjb25qdXIub3JnL3Nsb3NpbG8vdjIiLCJraWQiOiIxMDdiZGI4NTAxYzQxOWZhZDJmZGIyMGI0NjdkNGQwYTYyYTE2YTk4YzM1ZjJkYTBlYjNiMWZmOTI5Nzk1YWQ5In0=\",\"payload\":\"eyJzdWIiOiJob3N0L2V4YW1wbGUiLCJjaWRyIjpbImZlYzA6Oi82NCJdLCJleHAiOjE0MDE5NDIxNTIsImlhdCI6MTQwMTkzODU1Mn0=\",\"signature\":\"qSxy6gx0DbiIc-Wz_vZhBsYi1SCkHhzxfMGPnnG6MTqjlzy7ntmlU2H92GKGoqCRo6AaNLA_C3hA42PeEarV5nMoTj8XJO_kwhrt2Db2OX4u83VS0_enoztWEZG5s45V0Lv71lVR530j4LD-hpqhm_f4VuISkeH84u0zX7s1zKOlniuZP-abCAHh0htTnrVz9wKG0VywkCUmWYyNNqC2h8PRf64SvCWcQ6VleHpjO-ms8OeTw4ZzRbzKMi0mL6eTmQlbT3PeBArUaS0pNJPg9zdDQaL2XDOofvQmj6Yy_8RA4eCt9HEfTYEdriVqK-_9QCspbGzFVn9GTWf51MRi5dngV9ItsDoG9ktDtqFuMttv7TcqjftsIHZXZsAZ175E\"}".freeze
102
+ end
@@ -1,5 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
+ require 'active_support'
4
+ require 'active_support/core_ext/numeric/time'
5
+
3
6
  describe Slosilo::Key do
4
7
  include_context "with example key"
5
8
 
@@ -77,8 +80,8 @@ describe Slosilo::Key do
77
80
  end
78
81
  end
79
82
 
80
- let(:ciphertext) { "\x8B\xE6\xEC\x8C\xAB\xA4\xC0\x8EF\"\x0F\xD5Yh\xA1\aq\x00\xF5\xAC\xAB\v\a\xEC\xF6G\xA6\e\x14N\xFF\x11\x98\xDA\x19\xB5\x8994_:\xA0\xF8\x06l\xDC\x9B\xB1\xE8z\x83\xCC\x9A\x02E\x02tOhu\x92F]h".force_encoding("ASCII-8BIT") }
81
- let(:skey) { "\x15\xFF\xD4>\x9C\xF4\x0F\xB6\x04C\x18\xC1\x96\xC3\xE0T\xA3\xF5\xE8\x17\xA6\xE0\x86~rrw\xC3\xDF\x11)$\x9B\r@\x0E\xE4Zv\rw-\xFC\x1C\x84\x17\xBD\xDB\x12u\xCD\r\xFEo\xD5\xC8[\x8FEA\\\xA9\xA2F#\x8BH -\xFA\xF7\xA9\xEBf\x97\xAAT}\x8E*\xC0r\x944p\xD0\x9A\xE7\xBD\a;O\f\xEF\xE4B.y\xFA\xB4e@O\xBB\x15>y\xC9\t=\x01\xE1J\xF3X\xA9\x9E3\x04^H\x1F\xFF\x19C\x93ve)@\xF7\t_\xCF\xDE\xF1\xB7]\x83lL\xB8%A\x93p{\xE9Y\xBAu\xCE\x99T\xDC\xDF\xE7\x0FD%\xB9AXb\x1CW\x94$P\xBB\xE1g\xDEE\t\xC4\x92\x9E\xFEt\xDF\xD0\xEA\x03\xC4\x12\xA9\x02~u\xF4\x92 ;\xA0\xCE.\b+)\x05\xEDo\xA5cF\xF8\x12\xD7F\x97\xE44\xBF\xF1@\xA5\xC5\xA8\xE5\a\xE8ra<\x04\xB5\xA2\f\t\xF7T\x97\e\xF5(^\xAB\xA5%84\x10\xD1\x13e<\xCA/\xBF}%\xF6\xB1%\xB2".force_encoding("ASCII-8BIT") }
83
+ let(:ciphertext){ "G\xAD^\x17\x11\xBBQ9-b\x14\xF6\x92#Q0x\xF4\xAD\x1A\x92\xC3VZW\x89\x8E\x8Fg\x93\x05B\xF8\xD6O\xCFGCTp\b~\x916\xA3\x9AN\x8D\x961\x1F\xA3mSf&\xAD\xA77/]z\xA89\x01\xA7\xA9\x92\f".force_encoding('ASCII-8BIT') }
84
+ let(:skey){ "\x82\x93\xFAA\xA6wQA\xE1\xB5\xA6b\x8C.\xCF#I\x86I\x83u\x99\rTA\xEF\xC4\x91\xC5)-\xEBQ\xB1\xC0\xC6\xFF\x90L\xFE\x1E\x15\x81\x12\x16\xDD:A\xC5d\xE1B\xD2f@\xB8o\xB7+N\xB7\n\x92\xDC\x9E\xE3\x83\xB8>h\a\xC7\xCC\xCF\xD0t\x06\x8B\xA8\xBF\xEFe\xA4{\x88\f\xDD\roF\xEB.\xDA\xBF\x9D_0>\xF03c'\x1F!)*-\x19\x97\xAC\xD2\x1F(,6h\a\x93\xDB\x8E\x97\xF9\x1A\x11\x84\x11t\xD9\xB2\x85\xB0\x12\x7F\x03\x00O\x8F\xBE#\xFFb\xA5w\xF3g\xCF\xB4\xF2\xB7\xDBiA=\xA8\xFD1\xEC\xBF\xD7\x8E\xB6W>\x03\xACNBa\xBF\xFD\xC6\xB32\x8C\xE2\xF1\x87\x9C\xAE6\xD1\x12\vkl\xBB\xA0\xED\x9A\xEE6\xF2\xD9\xB4LL\xE2h/u_\xA1i=\x11x\x8DGha\x8EG\b+\x84[\x87\x8E\x01\x0E\xA5\xB0\x9F\xE9vSl\x18\xF3\xEA\xF4NH\xA8\xF1\x81\xBB\x98\x01\xE8p]\x18\x11f\xA3K\xA87c\xBB\x13X~K\xA2".force_encoding('ASCII-8BIT') }
82
85
  describe '#decrypt' do
83
86
  it "decrypts the symmetric key and then uses it to decrypt the ciphertext" do
84
87
  expect(subject.decrypt(ciphertext, skey)).to eq(plaintext)
@@ -120,7 +123,7 @@ describe Slosilo::Key do
120
123
  context "when given something else" do
121
124
  subject { Slosilo::Key.new "foo" }
122
125
  it "fails early" do
123
- expect { subject }.to raise_error
126
+ expect { subject }.to raise_error ArgumentError
124
127
  end
125
128
  end
126
129
  end
@@ -145,6 +148,19 @@ describe Slosilo::Key do
145
148
  expect(key.sign("this sentence is not this sentence")).to eq(expected_signature)
146
149
  end
147
150
  end
151
+
152
+ context "when given a Hash containing non-ascii characters" do
153
+ let(:unicode){ "adèle.dupuis" }
154
+ let(:encoded){
155
+ unicode.dup.tap{|s| s.force_encoding Encoding::ASCII_8BIT}
156
+ }
157
+ let(:hash){ {"data" => unicode} }
158
+
159
+ it "converts the value to raw bytes before signing it" do
160
+ expect(key).to receive(:sign_string).with("[[\"data\",\"#{encoded}\"]]").and_call_original
161
+ key.sign hash
162
+ end
163
+ end
148
164
  end
149
165
 
150
166
  describe "#signed_token" do
@@ -162,7 +178,50 @@ describe Slosilo::Key do
162
178
  subject { key.signed_token data }
163
179
  it { is_expected.to eq(expected_token) }
164
180
  end
165
-
181
+
182
+ describe "#validate_jwt" do
183
+ let(:token) do
184
+ instance_double Slosilo::JWT,
185
+ header: { 'alg' => 'conjur.org/slosilo/v2' },
186
+ claims: { 'iat' => Time.now.to_i },
187
+ string_to_sign: double("string to sign"),
188
+ signature: double("signature")
189
+ end
190
+
191
+ before do
192
+ allow(key).to receive(:verify_signature).with(token.string_to_sign, token.signature) { true }
193
+ end
194
+
195
+ it "verifies the signature" do
196
+ expect { key.validate_jwt token }.not_to raise_error
197
+ end
198
+
199
+ it "rejects unknown algorithm" do
200
+ token.header['alg'] = 'HS256' # we're not supporting standard algorithms
201
+ expect { key.validate_jwt token }.to raise_error /algorithm/
202
+ end
203
+
204
+ it "rejects bad signature" do
205
+ allow(key).to receive(:verify_signature).with(token.string_to_sign, token.signature) { false }
206
+ expect { key.validate_jwt token }.to raise_error /signature/
207
+ end
208
+
209
+ it "rejects expired token" do
210
+ token.claims['exp'] = 1.hour.ago.to_i
211
+ expect { key.validate_jwt token }.to raise_error /expired/
212
+ end
213
+
214
+ it "accepts unexpired token with implicit expiration" do
215
+ token.claims['iat'] = 5.minutes.ago
216
+ expect { key.validate_jwt token }.to_not raise_error
217
+ end
218
+
219
+ it "rejects token expired with implicit expiration" do
220
+ token.claims['iat'] = 10.minutes.ago.to_i
221
+ expect { key.validate_jwt token }.to raise_error /expired/
222
+ end
223
+ end
224
+
166
225
  describe "#token_valid?" do
167
226
  let(:data) { { "foo" => :bar } }
168
227
  let(:signature) { Base64::urlsafe_encode64 "\xB0\xCE{\x9FP\xEDV\x9C\xE7b\x8B[\xFAil\x87^\x96\x17Z\x97\x1D\xC2?B\x96\x9C\x8Ep-\xDF_\x8F\xC21\xD9^\xBC\n\x16\x04\x8DJ\xF6\xAF-\xEC\xAD\x03\xF9\xEE:\xDF\xB5\x8F\xF9\xF6\x81m\xAB\x9C\xAB1\x1E\x837\x8C\xFB\xA8P\xA8<\xEA\x1Dx\xCEd\xED\x84f\xA7\xB5t`\x96\xCC\x0F\xA9t\x8B\x9Fo\xBF\x92K\xFA\xFD\xC5?\x8F\xC68t\xBC\x9F\xDE\n$\xCA\xD2\x8F\x96\x0EtX2\x8Cl\x1E\x8Aa\r\x8D\xCAi\x86\x1A\xBD\x1D\xF7\xBC\x8561j\x91YlO\xFA(\x98\x10iq\xCC\xAF\x9BV\xC6\v\xBC\x10Xm\xCD\xFE\xAD=\xAA\x95,\xB4\xF7\xE8W\xB8\x83;\x81\x88\xE6\x01\xBA\xA5F\x91\x17\f\xCE\x80\x8E\v\x83\x9D<\x0E\x83\xF6\x8D\x03\xC0\xE8A\xD7\x90i\x1D\x030VA\x906D\x10\xA0\xDE\x12\xEF\x06M\xD8\x8B\xA9W\xC8\x9DTc\x8AJ\xA4\xC0\xD3!\xFA\x14\x89\xD1p\xB4J7\xA5\x04\xC2l\xDC8<\x04Y\xD8\xA4\xFB[\x89\xB1\xEC\xDA\xB8\xD7\xEA\x03Ja pinch of salt".force_encoding("ASCII-8BIT") }
@@ -60,7 +60,7 @@ describe Slosilo::Adapters::SequelAdapter do
60
60
  let(:db) { Sequel.sqlite }
61
61
  before do
62
62
  allow(subject).to receive(:create_model).and_call_original
63
- Sequel.cache_anonymous_models = false
63
+ Sequel::Model.cache_anonymous_models = false
64
64
  Sequel::Model.db = db
65
65
  end
66
66
  end