sandal 0.5.2 → 0.6.0

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
  SHA1:
3
- metadata.gz: b9335b993fe3eba12af0ce2a5f5b548495cb236e
4
- data.tar.gz: acc295000fad37701881ec296247358ea5e1527c
3
+ metadata.gz: 7ff4b80562db5433640998a394546147889b724e
4
+ data.tar.gz: 57ab4cfaf1b8145f179bebc192142428cc2d8b4a
5
5
  SHA512:
6
- metadata.gz: 4946603d929b6f6c063a458fe63d2f8847ecf3b97ef0c8e9fab3ea57119cd2bdee51c070dea1e693778e9a53b90c58a43a6c012cd4d24a59510e5593d0fe40ed
7
- data.tar.gz: 62f892126c09d7dd8845be99120230a4858a51d501efef370a8afb2f35569ab1167a252bb655f985c8cf85fccfbc0f4577e3550af67bd852f3631f8770d4d3f5
6
+ metadata.gz: 152b2ee352ff3d3ae11a4cc301e7f61b39f9b668678dd2049b0c3246e57b2633b9cbb0adc62d82cd4a920befd8d2b89fae13b5104e26b2a2e2edf9b216599ca2
7
+ data.tar.gz: c57f26aefdecb14a9d9966b21ca1e3fdf8016b9cc0b201f432a59f90a8f3030d87fac71cac3530fe2d449ed316286c21cbac37ddf946c18cbe11736bdc26182b
@@ -1,3 +1,9 @@
1
+ ## 0.6.0 (28 February 2014)
2
+
3
+ Breaking changes:
4
+
5
+ - Changed the behaviour around unsigned tokens so that they are rejected by default, to make the default settings more secure.
6
+
1
7
  ## 0.5.2 (03 January 2014)
2
8
 
3
9
  Improvements:
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Sandal [![Build Status](https://travis-ci.org/gregbeech/sandal.png?branch=master)](https://travis-ci.org/gregbeech/sandal) [![Coverage Status](https://coveralls.io/repos/gregbeech/sandal/badge.png?branch=master)](https://coveralls.io/r/gregbeech/sandal) [![Code Climate](https://codeclimate.com/github/gregbeech/sandal.png)](https://codeclimate.com/github/gregbeech/sandal) [![Dependency Status](https://gemnasium.com/gregbeech/sandal.png)](https://gemnasium.com/gregbeech/sandal)
1
+ # Sandal [![Gem Version](https://badge.fury.io/rb/sandal.png)](http://badge.fury.io/rb/sandal) [![Build Status](https://travis-ci.org/gregbeech/sandal.png?branch=master)](https://travis-ci.org/gregbeech/sandal) [![Coverage Status](https://coveralls.io/repos/gregbeech/sandal/badge.png?branch=master)](https://coveralls.io/r/gregbeech/sandal) [![Code Climate](https://codeclimate.com/github/gregbeech/sandal.png)](https://codeclimate.com/github/gregbeech/sandal) [![Dependency Status](https://gemnasium.com/gregbeech/sandal.png)](https://gemnasium.com/gregbeech/sandal)
2
2
 
3
3
  A Ruby library for creating and reading [JSON Web Tokens (JWT) draft-13](http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-13), supporting [JSON Web Signatures (JWS) draft-18](http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-18) and [JSON Web Encryption (JWE) draft-18](http://tools.ietf.org/html/draft-ietf-jose-json-web-encryption-18). See the [CHANGELOG](CHANGELOG.md) for version history.
4
4
 
@@ -114,6 +114,15 @@ Sandal.default! ignore_signature: true, ignore_exp: true
114
114
 
115
115
  These options can also be configured on a per-token basis by using a second `options` parameter in the block passed to the `decode` method.
116
116
 
117
+ Note that by default the library requires that the innermost token is signed as this is the most secure option. To enable decoding tokens that don't meet this policy you can disable it as shown below, although I'd strongly recommend that you just allow the token to be rejected!
118
+
119
+ ```ruby
120
+ payload = Sandal.decode_token(unsafe_token) do |header, options|
121
+ options[:signature_policy] = :none
122
+ Sandal::Sig::NONE
123
+ end
124
+ ```
125
+
117
126
  ## Contributing
118
127
 
119
128
  1. Fork it
@@ -50,6 +50,10 @@ module Sandal
50
50
  # max_clock_skew::
51
51
  # The maximum clock skew, in seconds, when validating times. If your server time is out of sync with the token
52
52
  # server then this can be increased to take that into account. It probably shouldn't be more than about 300.
53
+ # signature_policy::
54
+ # The policy for requiring signatures in tokens. The possible values are:
55
+ # - :strict (default) - The innermost token must be signed. This is the recommended policy.
56
+ # - :none - No signature is required. This _really_ isn't recommended.
53
57
  # valid_iss::
54
58
  # A list of valid token issuers, if validation of the issuer claim is required.
55
59
  # valid_aud::
@@ -59,6 +63,7 @@ module Sandal
59
63
  ignore_nbf: false,
60
64
  ignore_signature: false,
61
65
  max_clock_skew: 0,
66
+ signature_policy: :strict,
62
67
  valid_iss: [],
63
68
  valid_aud: []
64
69
  }
@@ -188,6 +193,9 @@ module Sandal
188
193
  payload
189
194
  end
190
195
  else
196
+ if options[:signature_policy] == :strict && !is_signed?(parts)
197
+ raise Sandal::UnsupportedTokenError, "The innermost token is not signed."
198
+ end
191
199
  parse_and_validate(payload, options)
192
200
  end
193
201
  end
@@ -196,10 +204,10 @@ module Sandal
196
204
 
197
205
  # Decodes and validates a signed JSON Web Token.
198
206
  def self.validate_signature(parts, signature, validator)
199
- validator ||= Sandal::Sig::NONE
207
+ raise UnsupportedTokenError, "Unsupported signature method." if validator.nil?
200
208
  secured_input = parts.take(2).join(".")
201
209
  unless validator.valid?(signature, secured_input)
202
- raise TokenError, "Invalid signature."
210
+ raise InvalidTokenError, "Invalid signature."
203
211
  end
204
212
  end
205
213
 
@@ -209,7 +217,7 @@ module Sandal
209
217
  parts[0] = Sandal::Json.load(parts[0])
210
218
  parts
211
219
  rescue
212
- raise TokenError, "Invalid token encoding."
220
+ raise InvalidTokenError, "Invalid token encoding."
213
221
  end
214
222
 
215
223
  # Parses the content of a token and validates the claims if is JSON claims.
@@ -1,4 +1,4 @@
1
1
  module Sandal
2
2
  # The semantic version of the library.
3
- VERSION = "0.5.2"
3
+ VERSION = "0.6.0"
4
4
  end
@@ -28,5 +28,5 @@ Gem::Specification.new do |s|
28
28
  s.add_development_dependency "redcarpet", ">= 2.2" unless RUBY_PLATFORM == "java" # for yard
29
29
  s.add_development_dependency "kramdown", ">= 1.0" if RUBY_PLATFORM == "java" # for yard
30
30
 
31
- s.requirements << "openssl 1.0.1c for EC signature methods"
31
+ s.requirements << "OpenSSL 1.0.1c for EC signature methods (1.0.1f recommended)"
32
32
  end
@@ -10,7 +10,8 @@ describe Sandal do
10
10
  private_key = OpenSSL::PKey::RSA.new(2048)
11
11
  encrypter = Sandal::Enc::A128CBC_HS256.new(Sandal::Enc::Alg::RSA1_5.new(private_key.public_key))
12
12
  token = Sandal.encrypt_token(payload, encrypter, { 'zip' => 'DEF' })
13
- decoded_payload = Sandal.decode_token(token) do |header|
13
+ decoded_payload = Sandal.decode_token(token) do |header, options|
14
+ options[:signature_policy] = :none
14
15
  Sandal::Enc::A128CBC_HS256.new(Sandal::Enc::Alg::RSA1_5.new(private_key))
15
16
  end
16
17
  expect(decoded_payload).to eq(payload)
@@ -32,6 +33,28 @@ describe Sandal do
32
33
 
33
34
  end
34
35
 
36
+ context "#decode_token" do
37
+
38
+ it 'does not accept tokens with no signatures by default' do
39
+ payload = 'some payload to be zipped'
40
+ token = Sandal.encode_token(payload, Sandal::Sig::NONE)
41
+ expect { Sandal.decode_token(token) do |header, options|
42
+ Sandal::Sig::NONE
43
+ end }.to raise_error Sandal::UnsupportedTokenError
44
+ end
45
+
46
+ it 'does not accept encrypted tokens with no signatures by default' do
47
+ payload = 'some payload to be zipped'
48
+ private_key = OpenSSL::PKey::RSA.new(2048)
49
+ encrypter = Sandal::Enc::A128CBC_HS256.new(Sandal::Enc::Alg::RSA1_5.new(private_key.public_key))
50
+ token = Sandal.encrypt_token(payload, encrypter)
51
+ expect { Sandal.decode_token(token) do |header, options|
52
+ Sandal::Enc::A128CBC_HS256.new(Sandal::Enc::Alg::RSA1_5.new(private_key))
53
+ end }.to raise_error Sandal::UnsupportedTokenError
54
+ end
55
+
56
+ end
57
+
35
58
  it 'raises a token error when the token format is invalid' do
36
59
  expect { Sandal.decode_token('not a valid token') }.to raise_error Sandal::TokenError
37
60
  end
@@ -43,42 +66,61 @@ describe Sandal do
43
66
  it 'encodes and decodes tokens with no signature' do
44
67
  payload = 'Hello, World'
45
68
  token = Sandal.encode_token(payload, nil)
46
- decoded_payload = Sandal.decode_token(token)
69
+ decoded_payload = Sandal.decode_token(token) do |header, options|
70
+ options[:signature_policy] = :none
71
+ Sandal::Sig::NONE
72
+ end
47
73
  expect(decoded_payload).to eq(payload)
48
74
  end
49
75
 
50
76
  it 'encodes and decodes tokens with "none" signature' do
51
77
  payload = 'Hello, World'
52
- token = Sandal.encode_token(payload, Sandal::Sig::None.instance)
53
- decoded_payload = Sandal.decode_token(token)
78
+ token = Sandal.encode_token(payload, Sandal::Sig::NONE)
79
+ decoded_payload = Sandal.decode_token(token) do |header, options|
80
+ options[:signature_policy] = :none
81
+ Sandal::Sig::NONE
82
+ end
54
83
  expect(decoded_payload).to eq(payload)
55
84
  end
56
85
 
57
86
  it 'decodes non-JSON payloads to a String' do
58
87
  token = Sandal.encode_token('not valid json', nil)
59
- expect(Sandal.decode_token(token)).to be_kind_of String
88
+ expect(Sandal.decode_token(token) do |header, options|
89
+ options[:signature_policy] = :none
90
+ Sandal::Sig::NONE
91
+ end).to be_kind_of String
60
92
  end
61
93
 
62
94
  it 'decodes JSON payloads to a Hash' do
63
95
  token = Sandal.encode_token({ 'valid' => 'json' }, nil)
64
- expect(Sandal.decode_token(token)).to be_kind_of Hash
96
+ expect(Sandal.decode_token(token) do |header, options|
97
+ options[:signature_policy] = :none
98
+ Sandal::Sig::NONE
99
+ end).to be_kind_of Hash
65
100
  end
66
101
 
67
102
  it 'raises a claim error when the expiry date is far in the past' do
68
103
  token = Sandal.encode_token({ 'exp' => (Time.now - 600).to_i }, nil)
69
- expect { Sandal.decode_token(token) }.to raise_error Sandal::ClaimError
104
+ expect { Sandal.decode_token(token) do |header, options|
105
+ options[:signature_policy] = :none
106
+ Sandal::Sig::NONE
107
+ end }.to raise_error Sandal::ClaimError
70
108
  end
71
109
 
72
110
  it 'raises a claim error when the expiry date is invalid' do
73
111
  token = Sandal.encode_token({ 'exp' => 'invalid value' }, nil)
74
- expect { Sandal.decode_token(token) }.to raise_error Sandal::ClaimError
112
+ expect { Sandal.decode_token(token) do |header, options|
113
+ options[:signature_policy] = :none
114
+ Sandal::Sig::NONE
115
+ end }.to raise_error Sandal::ClaimError
75
116
  end
76
117
 
77
118
  it 'does not raise an error when the expiry date is in the past but validation is disabled' do
78
119
  token = Sandal.encode_token({ 'exp' => (Time.now - 600).to_i }, nil)
79
120
  Sandal.decode_token(token) do |header, options|
80
121
  options[:ignore_exp] = true
81
- nil
122
+ options[:signature_policy] = :none
123
+ Sandal::Sig::NONE
82
124
  end
83
125
  end
84
126
 
@@ -86,30 +128,41 @@ describe Sandal do
86
128
  token = Sandal.encode_token({ 'exp' => (Time.now - 60).to_i }, nil)
87
129
  Sandal.decode_token(token) do |header, options|
88
130
  options[:max_clock_skew] = 300
89
- nil
131
+ options[:signature_policy] = :none
132
+ Sandal::Sig::NONE
90
133
  end
91
134
  end
92
135
 
93
136
  it 'does not raise an error when the expiry date is valid' do
94
137
  token = Sandal.encode_token({ 'exp' => (Time.now + 60).to_i }, nil)
95
- Sandal.decode_token(token)
138
+ Sandal.decode_token(token) do |header, options|
139
+ options[:signature_policy] = :none
140
+ Sandal::Sig::NONE
141
+ end
96
142
  end
97
143
 
98
144
  it 'raises a claim error when the not-before date is far in the future' do
99
145
  token = Sandal.encode_token({ 'nbf' => (Time.now + 600).to_i }, nil)
100
- expect { Sandal.decode_token(token) }.to raise_error Sandal::ClaimError
146
+ expect { Sandal.decode_token(token) do |header, options|
147
+ options[:signature_policy] = :none
148
+ Sandal::Sig::NONE
149
+ end }.to raise_error Sandal::ClaimError
101
150
  end
102
151
 
103
152
  it 'raises a claim error when the not-before date is invalid' do
104
153
  token = Sandal.encode_token({ 'nbf' => 'invalid value' }, nil)
105
- expect { Sandal.decode_token(token) }.to raise_error Sandal::ClaimError
154
+ expect { Sandal.decode_token(token) do |header, options|
155
+ options[:signature_policy] = :none
156
+ Sandal::Sig::NONE
157
+ end }.to raise_error Sandal::ClaimError
106
158
  end
107
159
 
108
160
  it 'does not raise an error when the not-before date is in the future but validation is disabled' do
109
161
  token = Sandal.encode_token({ 'nbf' => (Time.now + 600).to_i }, nil)
110
162
  Sandal.decode_token(token) do |header, options|
111
163
  options[:ignore_nbf] = true
112
- nil
164
+ options[:signature_policy] = :none
165
+ Sandal::Sig::NONE
113
166
  end
114
167
  end
115
168
 
@@ -117,20 +170,25 @@ describe Sandal do
117
170
  token = Sandal.encode_token({ 'nbf' => (Time.now + 60).to_i }, nil)
118
171
  Sandal.decode_token(token) do |header, options|
119
172
  options[:max_clock_skew] = 300
120
- nil
173
+ options[:signature_policy] = :none
174
+ Sandal::Sig::NONE
121
175
  end
122
176
  end
123
177
 
124
178
  it 'does not raise an error when the not-before is valid' do
125
179
  token = Sandal.encode_token({ 'nbf' => (Time.now - 60).to_i }, nil)
126
- Sandal.decode_token(token)
180
+ Sandal.decode_token(token) do |header, options|
181
+ options[:signature_policy] = :none
182
+ Sandal::Sig::NONE
183
+ end
127
184
  end
128
185
 
129
186
  it 'raises a claim error when the issuer is not valid' do
130
187
  token = Sandal.encode_token({ 'iss' => 'example.org' }, nil)
131
188
  expect { Sandal.decode_token(token) do |header, options|
132
189
  options[:valid_iss] = ['example.net']
133
- nil
190
+ options[:signature_policy] = :none
191
+ Sandal::Sig::NONE
134
192
  end }.to raise_error Sandal::ClaimError
135
193
  end
136
194
 
@@ -138,7 +196,8 @@ describe Sandal do
138
196
  token = Sandal.encode_token({ 'iss' => 'example.org' }, nil)
139
197
  Sandal.decode_token(token) do |header, options|
140
198
  options[:valid_iss] = ['example.org', 'example.com']
141
- nil
199
+ options[:signature_policy] = :none
200
+ Sandal::Sig::NONE
142
201
  end
143
202
  end
144
203
 
@@ -146,7 +205,8 @@ describe Sandal do
146
205
  token = Sandal.encode_token({ 'aud' => 'example.com' }, nil)
147
206
  expect { Sandal.decode_token(token) do |header, options|
148
207
  options[:valid_aud] = ['example.net']
149
- nil
208
+ options[:signature_policy] = :none
209
+ Sandal::Sig::NONE
150
210
  end }.to raise_error Sandal::ClaimError
151
211
  end
152
212
 
@@ -154,7 +214,8 @@ describe Sandal do
154
214
  token = Sandal.encode_token({ 'aud' => ['example.org', 'example.com'] }, nil)
155
215
  expect { Sandal.decode_token(token) do |header, options|
156
216
  options[:valid_aud] = ['example.net']
157
- nil
217
+ options[:signature_policy] = :none
218
+ Sandal::Sig::NONE
158
219
  end }.to raise_error Sandal::ClaimError
159
220
  end
160
221
 
@@ -162,7 +223,8 @@ describe Sandal do
162
223
  token = Sandal.encode_token({ 'aud' => 'example.net' }, nil)
163
224
  Sandal.decode_token(token) do |header, options|
164
225
  options[:valid_aud] = ['example.net']
165
- nil
226
+ options[:signature_policy] = :none
227
+ Sandal::Sig::NONE
166
228
  end
167
229
  end
168
230
 
@@ -170,7 +232,8 @@ describe Sandal do
170
232
  token = Sandal.encode_token({ 'aud' => ['example.com', 'example.net'] }, nil)
171
233
  Sandal.decode_token(token) do |header, options|
172
234
  options[:valid_aud] = ['example.net']
173
- nil
235
+ options[:signature_policy] = :none
236
+ Sandal::Sig::NONE
174
237
  end
175
238
  end
176
239
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sandal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Beech
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-03 00:00:00.000000000 Z
11
+ date: 2014-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -178,9 +178,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
178
178
  - !ruby/object:Gem::Version
179
179
  version: '0'
180
180
  requirements:
181
- - openssl 1.0.1c for EC signature methods
181
+ - OpenSSL 1.0.1c for EC signature methods (1.0.1f recommended)
182
182
  rubyforge_project:
183
- rubygems_version: 2.2.0
183
+ rubygems_version: 2.2.2
184
184
  signing_key:
185
185
  specification_version: 4
186
186
  summary: A JSON Web Token (JWT) library.