jwt-multisig 1.0.0.beta.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -4
- data/Rakefile +2 -0
- data/lib/jwt-multisig/version.rb +1 -1
- data/lib/jwt-multisig.rb +12 -7
- data/test/test-jwt-verificator.rb +9 -0
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 196758ff74f27b332271c1265497dd698b50d78316fa4b12d85d091c9867876f
|
4
|
+
data.tar.gz: df16be95f6fcb777019ac810b851ccd4a2e904478e5a5e6a83f9a2bfd857c5e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e2d773f5b81e57fd3ea73b1f76654ff6ccbbb1c3bda2e09562e43d235567af3d257f1e75dbf6d21388064bf06cca68bc5473c3e75b19294e61cb5e77196a9ff
|
7
|
+
data.tar.gz: c265d82ff2dc690a3f9652364af564fd5184d898a483c1e02a55c29d72e3c344d954d515b0f3aaa0c6462e40a06b0a08047785774edc734f10d4629f5e3847ed
|
data/Gemfile.lock
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
jwt-multisig (1.0.0
|
4
|
+
jwt-multisig (1.0.0)
|
5
5
|
activesupport (>= 4.0, < 6.0)
|
6
6
|
jwt (~> 2.1)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
activesupport (5.1.
|
11
|
+
activesupport (5.1.6)
|
12
12
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
13
|
-
i18n (
|
13
|
+
i18n (>= 0.7, < 2)
|
14
14
|
minitest (~> 5.1)
|
15
15
|
tzinfo (~> 1.1)
|
16
16
|
concurrent-ruby (1.0.5)
|
17
|
-
i18n (0.
|
17
|
+
i18n (1.0.0)
|
18
18
|
concurrent-ruby (~> 1.0)
|
19
19
|
jwt (2.1.0)
|
20
20
|
memoist (0.16.0)
|
data/Rakefile
CHANGED
data/lib/jwt-multisig/version.rb
CHANGED
data/lib/jwt-multisig.rb
CHANGED
@@ -5,6 +5,7 @@ require "jwt"
|
|
5
5
|
require "openssl"
|
6
6
|
require "active_support/core_ext/hash/keys"
|
7
7
|
require "active_support/core_ext/hash/slice"
|
8
|
+
require "active_support/core_ext/hash/indifferent_access"
|
8
9
|
|
9
10
|
module JWT
|
10
11
|
#
|
@@ -39,8 +40,11 @@ module JWT
|
|
39
40
|
# @raise [JWT::EncodeError]
|
40
41
|
def generate_jwt(payload, private_keychain, algorithms)
|
41
42
|
proxy_exception JWT::EncodeError do
|
43
|
+
algorithms_mapping = algorithms.with_indifferent_access
|
42
44
|
{ payload: base64_encode(payload.to_json),
|
43
|
-
signatures: private_keychain.map
|
45
|
+
signatures: private_keychain.map do |id, value|
|
46
|
+
generate_jws(payload, id, value, algorithms_mapping.fetch(id))
|
47
|
+
end }
|
44
48
|
end
|
45
49
|
end
|
46
50
|
|
@@ -112,12 +116,13 @@ module JWT
|
|
112
116
|
# The returning value contains payload, list of verified, and unverified signatures (key ID).
|
113
117
|
# Example:
|
114
118
|
# { payload: { sub: "session", profile: { email: "username@mailbox.example" },
|
115
|
-
# verified: ["backend-1.mycompany.example", "backend-3.mycompany.example"],
|
116
|
-
# unverified: ["backend-2.mycompany.example"] }
|
119
|
+
# verified: [:"backend-1.mycompany.example", :"backend-3.mycompany.example"],
|
120
|
+
# unverified: [:"backend-2.mycompany.example"] }
|
117
121
|
# }
|
118
122
|
# @raise [JWT::DecodeError]
|
119
123
|
def verify_jwt(jwt, public_keychain, options = {})
|
120
124
|
proxy_exception JWT::DecodeError do
|
125
|
+
keychain = public_keychain.with_indifferent_access
|
121
126
|
serialized_payload = base64_decode(jwt.fetch("payload"))
|
122
127
|
payload = JSON.parse(serialized_payload)
|
123
128
|
verified = []
|
@@ -125,7 +130,7 @@ module JWT
|
|
125
130
|
|
126
131
|
jwt.fetch("signatures").each do |jws|
|
127
132
|
key_id = jws.fetch("header").fetch("kid")
|
128
|
-
if
|
133
|
+
if keychain.key?(key_id)
|
129
134
|
verify_jws(jws, payload, public_keychain, options)
|
130
135
|
verified << key_id
|
131
136
|
else
|
@@ -133,8 +138,8 @@ module JWT
|
|
133
138
|
end
|
134
139
|
end
|
135
140
|
{ payload: payload.deep_symbolize_keys,
|
136
|
-
verified: verified.uniq,
|
137
|
-
unverified: unverified.uniq }
|
141
|
+
verified: verified.uniq.map(&:to_sym),
|
142
|
+
unverified: unverified.uniq.map(&:to_sym) }
|
138
143
|
end
|
139
144
|
end
|
140
145
|
|
@@ -195,7 +200,7 @@ module JWT
|
|
195
200
|
serialized_payload = payload.to_json
|
196
201
|
encoded_payload = base64_encode(serialized_payload)
|
197
202
|
signature = jws.fetch("signature")
|
198
|
-
public_key = public_keychain.fetch(jws.fetch("header").fetch("kid"))
|
203
|
+
public_key = public_keychain.with_indifferent_access.fetch(jws.fetch("header").fetch("kid"))
|
199
204
|
jwt = [encoded_header, encoded_payload, signature].join(".")
|
200
205
|
algorithm = JSON.parse(serialized_header).fetch("alg")
|
201
206
|
JWT.decode(jwt, to_pem_or_key(public_key, algorithm), true, options.merge(algorithms: [algorithm])).first
|
@@ -31,6 +31,15 @@ class JWTVerificatorTest < Test::Unit::TestCase
|
|
31
31
|
example jwt, {}, {}, %({"payload":{"xxx":"zzz"},"verified":[],"unverified":["hoegerrenner.info","powlowski.info"]})
|
32
32
|
end
|
33
33
|
|
34
|
+
def test_both_symbols_and_strings_are_supported
|
35
|
+
jwt = %({"payload":"eyJpc3MiOiJmb28iLCJiYXIiOnsiYmF6IjoicXV4In19","signatures":[{"protected":"eyJhbGciOiJIUzUxMiJ9","header":{"kid":"ebert.biz"},"signature":"1koPnSwejNF5aCRsqlySX9Td7_gc-dfUkko5G0Svccw-WkBYrwoJJwRJ2Op_-OxjoqSe3ViBGGCbgVUz0khuJQ"},{"protected":"eyJhbGciOiJIUzI1NiJ9","header":{"kid":"wisoky.co"},"signature":"AqtFKTlaVDqg2dOfLBODMhcBlg1gm9ejn6hYQynTyto"},{"protected":"eyJhbGciOiJSUzM4NCJ9","header":{"kid":"hoegerrenner.info"},"signature":"LR9TpJTLwgducdCkN1KmfwXXxd3pp7Xe5fJXJZZM8FVrFrVOEAGQcPnMPIgfPA1UckIXnzih46j4qPOQdotVHEvYvUuvLLT8QQi8y6-vBMlsP-cQehKGpI1T4N5qPzvJqPmhVzZYedWzlvr-VV9wd0BYeBgr65m9BSpFjLFhWVH4NJZuHFPxeYuDEpYoM-lPHdTzdf1E8xd_xwbpz9WpNh0MQib387-wakGWz-UGt9BmJLU8KV01FTAoR0EO9rQfIm5HQ3wGQ7t8U4N4HsOmsXkWF_fRgxjhMHeChDES2awwB4G4KCNw-6ezSBCD7FZcxzbCL2657OEPHNuHA36M91j54jjm1tweYhYJxuUOk5c8j_wSxtieeaORCxOrPp3mshHS_FE0sI_TNNBsIDI_sQwiS08y3d6tv7H4a_MZj_Pe7JWJ3TXlcsaSHy3xuSLYxCZQeLBwJtyz2ERCZOA9ew0BY34tpRwDKxbgF51X7t7uilYxnBn2rBdQeWQKb9q2"}]})
|
36
|
+
keychain = {
|
37
|
+
"hoegerrenner.info": public_keychain["hoegerrenner.info"],
|
38
|
+
"wisoky.co": public_keychain["wisoky.co"],
|
39
|
+
"ebert.biz" => public_keychain["ebert.biz"] }
|
40
|
+
example jwt, keychain, { iss: "foo" }, %({"payload":{"iss":"foo","bar":{"baz":"qux"}},"verified":["ebert.biz","wisoky.co","hoegerrenner.info"],"unverified":[]})
|
41
|
+
end
|
42
|
+
|
34
43
|
private
|
35
44
|
|
36
45
|
def example(jwt, keychain, options, expected)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jwt-multisig
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- RubyKube
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-03
|
11
|
+
date: 2018-04-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jwt
|
@@ -98,9 +98,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
98
98
|
version: '0'
|
99
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
103
|
+
version: '0'
|
104
104
|
requirements: []
|
105
105
|
rubyforge_project:
|
106
106
|
rubygems_version: 2.7.3
|