jwt-multisig 1.0.0.beta.2 → 1.0.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/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
|