json-jwt 1.10.1 → 1.15.3.1
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/.github/FUNDING.yml +3 -0
- data/.github/workflows/test_ruby.yml +30 -0
- data/.gitmodules +1 -1
- data/.travis.yml +5 -4
- data/README.md +11 -0
- data/VERSION +1 -1
- data/json-jwt.gemspec +3 -1
- data/lib/json/jose.rb +4 -4
- data/lib/json/jwe.rb +7 -6
- data/lib/json/jwk/jwkizable.rb +2 -0
- data/lib/json/jwk/set/fetcher/debugger/request_filter.rb +34 -0
- data/lib/json/jwk/set/fetcher.rb +87 -0
- data/lib/json/jwk/set.rb +6 -0
- data/lib/json/jwk.rb +55 -27
- data/lib/json/jws.rb +20 -22
- data/lib/json/jwt.rb +12 -1
- metadata +39 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3d9dceefdfb0168531cd68668848730898141b097c5541cde5cbb95a1bc24d7
|
4
|
+
data.tar.gz: 9dd27ddf48a2102ee1da5b8a7da411d10393fb622570a170b63dc328d50db7b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: edbf0b0eb0521841aae74427293f66595ab30dee065b59b21bf0e3bd57f929b8d700caa67d8458e6e832819d962998862067eb8de0ea5530db967f89e4b19cbc
|
7
|
+
data.tar.gz: d7dcc87bf09ef1ddcf9b81306c41db9286e62f9f9b90c7838a1073f6d88cdc8a8114be0834dc54c2b1e4a69a7355771257b0093ec63b1554b3bfaeab685b022a
|
data/.github/FUNDING.yml
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
name: Test Ruby
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
pull_request:
|
6
|
+
|
7
|
+
permissions:
|
8
|
+
contents: read
|
9
|
+
|
10
|
+
jobs:
|
11
|
+
test:
|
12
|
+
strategy:
|
13
|
+
matrix:
|
14
|
+
os: ['ubuntu-20.04']
|
15
|
+
ruby-version: ['2.6', '2.7', '3.0', '3.1']
|
16
|
+
# ubuntu 22.04 only supports ssl 3 and thus only ruby 3.1
|
17
|
+
include:
|
18
|
+
- os: 'ubuntu-22.04'
|
19
|
+
ruby-version: '3.1'
|
20
|
+
runs-on: ${{ matrix.os }}
|
21
|
+
|
22
|
+
steps:
|
23
|
+
- uses: actions/checkout@v3
|
24
|
+
- name: Set up Ruby
|
25
|
+
uses: ruby/setup-ruby@v1
|
26
|
+
with:
|
27
|
+
ruby-version: ${{ matrix.ruby-version }}
|
28
|
+
bundler-cache: true
|
29
|
+
- name: Run tests
|
30
|
+
run: bundle exec rake
|
data/.gitmodules
CHANGED
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -49,6 +49,17 @@ input = "jwt_header.jwt_claims.jwt_signature"
|
|
49
49
|
JSON::JWT.decode(input, public_key)
|
50
50
|
```
|
51
51
|
|
52
|
+
If you need to get a JWK from `jwks_uri` of OpenID Connect IdP, you can use `JSON::JWK::Set::Fetcher` to fetch (& optionally cache) it.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
# JWK Set Fetching & Caching
|
56
|
+
# NOTE: Optionally by setting cache instance, JWKs are cached by kid.
|
57
|
+
JSON::JWK::Set::Fetcher.cache = Rails.cache
|
58
|
+
|
59
|
+
JSON::JWK::Set::Fetcher.fetch(jwks_uri, kid: kid)
|
60
|
+
# => returns JSON::JWK instance or raise JSON::JWK::Set::KidNotFound
|
61
|
+
```
|
62
|
+
|
52
63
|
For more details, read [Documentation Wiki](https://github.com/nov/json-jwt/wiki).
|
53
64
|
|
54
65
|
## Note on Patches/Pull Requests
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.15.3.1
|
data/json-jwt.gemspec
CHANGED
@@ -12,12 +12,14 @@ Gem::Specification.new do |gem|
|
|
12
12
|
end
|
13
13
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
14
14
|
gem.require_paths = ['lib']
|
15
|
-
gem.required_ruby_version = '>= 2.
|
15
|
+
gem.required_ruby_version = '>= 2.4'
|
16
16
|
gem.add_runtime_dependency 'activesupport', '>= 4.2'
|
17
17
|
gem.add_runtime_dependency 'bindata'
|
18
18
|
gem.add_runtime_dependency 'aes_key_wrap'
|
19
|
+
gem.add_runtime_dependency 'httpclient'
|
19
20
|
gem.add_development_dependency 'rake'
|
20
21
|
gem.add_development_dependency 'simplecov'
|
22
|
+
gem.add_development_dependency 'webmock'
|
21
23
|
gem.add_development_dependency 'rspec'
|
22
24
|
gem.add_development_dependency 'rspec-its'
|
23
25
|
end
|
data/lib/json/jose.rb
CHANGED
@@ -7,9 +7,11 @@ module JSON
|
|
7
7
|
included do
|
8
8
|
extend ClassMethods
|
9
9
|
register_header_keys :alg, :jku, :jwk, :x5u, :x5t, :x5c, :kid, :typ, :cty, :crit
|
10
|
+
|
11
|
+
# NOTE: not used anymore in this gem, but keeping in case developers are calling it.
|
10
12
|
alias_method :algorithm, :alg
|
11
13
|
|
12
|
-
|
14
|
+
attr_writer :header
|
13
15
|
def header
|
14
16
|
@header ||= {}
|
15
17
|
end
|
@@ -24,9 +26,7 @@ module JSON
|
|
24
26
|
when JSON::JWK
|
25
27
|
key.to_key
|
26
28
|
when JSON::JWK::Set
|
27
|
-
key
|
28
|
-
jwk[:kid] && jwk[:kid] == kid
|
29
|
-
end&.to_key or raise JWK::Set::KidNotFound
|
29
|
+
key[kid]&.to_key or raise JWK::Set::KidNotFound
|
30
30
|
else
|
31
31
|
key
|
32
32
|
end
|
data/lib/json/jwe.rb
CHANGED
@@ -14,9 +14,10 @@ module JSON
|
|
14
14
|
|
15
15
|
attr_accessor(
|
16
16
|
:public_key_or_secret, :private_key_or_secret,
|
17
|
-
:plain_text, :cipher_text, :
|
18
|
-
:content_encryption_key, :
|
17
|
+
:plain_text, :cipher_text, :iv, :auth_data,
|
18
|
+
:content_encryption_key, :encryption_key, :mac_key
|
19
19
|
)
|
20
|
+
attr_writer :jwe_encrypted_key, :authentication_tag
|
20
21
|
|
21
22
|
register_header_keys :enc, :epk, :zip, :apu, :apv
|
22
23
|
alias_method :encryption_method, :enc
|
@@ -106,7 +107,7 @@ module JSON
|
|
106
107
|
end
|
107
108
|
|
108
109
|
def dir?
|
109
|
-
:dir ==
|
110
|
+
:dir == alg&.to_sym
|
110
111
|
end
|
111
112
|
|
112
113
|
def cipher
|
@@ -158,7 +159,7 @@ module JSON
|
|
158
159
|
# encryption
|
159
160
|
|
160
161
|
def jwe_encrypted_key
|
161
|
-
@jwe_encrypted_key ||= case
|
162
|
+
@jwe_encrypted_key ||= case alg&.to_sym
|
162
163
|
when :RSA1_5
|
163
164
|
public_key_or_secret.public_encrypt content_encryption_key
|
164
165
|
when :'RSA-OAEP'
|
@@ -210,7 +211,7 @@ module JSON
|
|
210
211
|
|
211
212
|
def decrypt_content_encryption_key
|
212
213
|
fake_content_encryption_key = generate_content_encryption_key # NOTE: do this always not to make timing difference
|
213
|
-
case
|
214
|
+
case alg&.to_sym
|
214
215
|
when :RSA1_5
|
215
216
|
private_key_or_secret.private_decrypt jwe_encrypted_key
|
216
217
|
when :'RSA-OAEP'
|
@@ -253,7 +254,7 @@ module JSON
|
|
253
254
|
raise InvalidFormat.new("Invalid JWE Format. JWE should include #{NUM_OF_SEGMENTS} segments.")
|
254
255
|
end
|
255
256
|
jwe = new
|
256
|
-
_header_json_, jwe.jwe_encrypted_key, jwe.iv, jwe.cipher_text, jwe.authentication_tag = input.split('.').collect do |segment|
|
257
|
+
_header_json_, jwe.jwe_encrypted_key, jwe.iv, jwe.cipher_text, jwe.authentication_tag = input.split('.', NUM_OF_SEGMENTS).collect do |segment|
|
257
258
|
begin
|
258
259
|
Base64.urlsafe_decode64 segment
|
259
260
|
rescue ArgumentError
|
data/lib/json/jwk/jwkizable.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
module JSON
|
2
|
+
class JWK
|
3
|
+
class Set
|
4
|
+
module Fetcher
|
5
|
+
module Debugger
|
6
|
+
class RequestFilter
|
7
|
+
# Callback called in HTTPClient (before sending a request)
|
8
|
+
# request:: HTTP::Message
|
9
|
+
def filter_request(request)
|
10
|
+
started = "======= [JSON::JWK::Set::Fetcher] HTTP REQUEST STARTED ======="
|
11
|
+
log started, request.dump
|
12
|
+
end
|
13
|
+
|
14
|
+
# Callback called in HTTPClient (after received a response)
|
15
|
+
# request:: HTTP::Message
|
16
|
+
# response:: HTTP::Message
|
17
|
+
def filter_response(request, response)
|
18
|
+
finished = "======= [JSON::JWK::Set::Fetcher] HTTP REQUEST FINISHED ======="
|
19
|
+
log '-' * 50, response.dump, finished
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def log(*outputs)
|
25
|
+
outputs.each do |output|
|
26
|
+
JSON::JWK::Set::Fetcher.logger.info output
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module JSON
|
2
|
+
class JWK
|
3
|
+
class Set
|
4
|
+
module Fetcher
|
5
|
+
class Cache
|
6
|
+
def fetch(cache_key, options = {})
|
7
|
+
yield
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.logger
|
12
|
+
@@logger
|
13
|
+
end
|
14
|
+
def self.logger=(logger)
|
15
|
+
@@logger = logger
|
16
|
+
end
|
17
|
+
self.logger = Logger.new(STDOUT)
|
18
|
+
self.logger.progname = 'JSON::JWK::Set::Fetcher'
|
19
|
+
|
20
|
+
def self.debugging?
|
21
|
+
@@debugging
|
22
|
+
end
|
23
|
+
def self.debugging=(boolean)
|
24
|
+
@@debugging = boolean
|
25
|
+
end
|
26
|
+
def self.debug!
|
27
|
+
self.debugging = true
|
28
|
+
end
|
29
|
+
def self.debug(&block)
|
30
|
+
original = self.debugging?
|
31
|
+
debug!
|
32
|
+
yield
|
33
|
+
ensure
|
34
|
+
self.debugging = original
|
35
|
+
end
|
36
|
+
self.debugging = false
|
37
|
+
|
38
|
+
def self.http_client
|
39
|
+
_http_client_ = HTTPClient.new(
|
40
|
+
agent_name: "JSON::JWK::Set::Fetcher (#{JSON::JWT::VERSION})"
|
41
|
+
)
|
42
|
+
|
43
|
+
# NOTE: httpclient gem seems stopped maintaining root certtificate set, use OS default.
|
44
|
+
_http_client_.ssl_config.clear_cert_store
|
45
|
+
_http_client_.ssl_config.cert_store.set_default_paths
|
46
|
+
|
47
|
+
_http_client_.request_filter << Debugger::RequestFilter.new if debugging?
|
48
|
+
http_config.try(:call, _http_client_)
|
49
|
+
_http_client_
|
50
|
+
end
|
51
|
+
def self.http_config(&block)
|
52
|
+
@@http_config ||= block
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.cache=(cache)
|
56
|
+
@@cache = cache
|
57
|
+
end
|
58
|
+
def self.cache
|
59
|
+
@@cache
|
60
|
+
end
|
61
|
+
self.cache = Cache.new
|
62
|
+
|
63
|
+
def self.fetch(jwks_uri, kid:, auto_detect: true, **options)
|
64
|
+
cache_key = [
|
65
|
+
'json:jwk:set',
|
66
|
+
OpenSSL::Digest::MD5.hexdigest(jwks_uri),
|
67
|
+
kid
|
68
|
+
].collect(&:to_s).join(':')
|
69
|
+
|
70
|
+
jwks = Set.new(
|
71
|
+
JSON.parse(
|
72
|
+
cache.fetch(cache_key, options) do
|
73
|
+
http_client.get_content(jwks_uri)
|
74
|
+
end
|
75
|
+
)
|
76
|
+
)
|
77
|
+
|
78
|
+
if auto_detect
|
79
|
+
jwks[kid] or raise KidNotFound
|
80
|
+
else
|
81
|
+
jwks
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/json/jwk/set.rb
CHANGED
@@ -19,6 +19,12 @@ module JSON
|
|
19
19
|
'application/jwk-set+json'
|
20
20
|
end
|
21
21
|
|
22
|
+
def [](kid)
|
23
|
+
detect do |jwk|
|
24
|
+
jwk[:kid] && jwk[:kid] == kid
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
22
28
|
def as_json(options = {})
|
23
29
|
# NOTE: Array.new wrapper is requied to avoid CircularReferenceError
|
24
30
|
{keys: Array.new(self)}
|
data/lib/json/jwk.rb
CHANGED
@@ -50,8 +50,6 @@ module JSON
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
private
|
54
|
-
|
55
53
|
def rsa?
|
56
54
|
self[:kty]&.to_sym == :RSA
|
57
55
|
end
|
@@ -64,12 +62,6 @@ module JSON
|
|
64
62
|
self[:kty]&.to_sym == :oct
|
65
63
|
end
|
66
64
|
|
67
|
-
def calculate_default_kid
|
68
|
-
self[:kid] = thumbprint
|
69
|
-
rescue
|
70
|
-
# ignore
|
71
|
-
end
|
72
|
-
|
73
65
|
def normalize
|
74
66
|
case
|
75
67
|
when rsa?
|
@@ -95,28 +87,43 @@ module JSON
|
|
95
87
|
end
|
96
88
|
end
|
97
89
|
|
90
|
+
private
|
91
|
+
|
92
|
+
def calculate_default_kid
|
93
|
+
self[:kid] = thumbprint
|
94
|
+
rescue
|
95
|
+
# ignore
|
96
|
+
end
|
97
|
+
|
98
98
|
def to_rsa_key
|
99
99
|
e, n, d, p, q, dp, dq, qi = [:e, :n, :d, :p, :q, :dp, :dq, :qi].collect do |key|
|
100
100
|
if self[key]
|
101
101
|
OpenSSL::BN.new Base64.urlsafe_decode64(self[key]), 2
|
102
102
|
end
|
103
103
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
104
|
+
|
105
|
+
# Public key
|
106
|
+
data_sequence = OpenSSL::ASN1::Sequence([
|
107
|
+
OpenSSL::ASN1::Integer(n),
|
108
|
+
OpenSSL::ASN1::Integer(e),
|
109
|
+
])
|
110
|
+
|
111
|
+
if d && p && q && dp && dq && qi
|
112
|
+
data_sequence = OpenSSL::ASN1::Sequence([
|
113
|
+
OpenSSL::ASN1::Integer(0),
|
114
|
+
OpenSSL::ASN1::Integer(n),
|
115
|
+
OpenSSL::ASN1::Integer(e),
|
116
|
+
OpenSSL::ASN1::Integer(d),
|
117
|
+
OpenSSL::ASN1::Integer(p),
|
118
|
+
OpenSSL::ASN1::Integer(q),
|
119
|
+
OpenSSL::ASN1::Integer(dp),
|
120
|
+
OpenSSL::ASN1::Integer(dq),
|
121
|
+
OpenSSL::ASN1::Integer(qi),
|
122
|
+
])
|
118
123
|
end
|
119
|
-
|
124
|
+
|
125
|
+
asn1 = OpenSSL::ASN1::Sequence(data_sequence)
|
126
|
+
OpenSSL::PKey::RSA.new(asn1.to_der)
|
120
127
|
end
|
121
128
|
|
122
129
|
def to_ec_key
|
@@ -127,6 +134,8 @@ module JSON
|
|
127
134
|
'secp384r1'
|
128
135
|
when :'P-521'
|
129
136
|
'secp521r1'
|
137
|
+
when :secp256k1
|
138
|
+
'secp256k1'
|
130
139
|
else
|
131
140
|
raise UnknownAlgorithm.new('Unknown EC Curve')
|
132
141
|
end
|
@@ -135,13 +144,32 @@ module JSON
|
|
135
144
|
Base64.urlsafe_decode64(self[key])
|
136
145
|
end
|
137
146
|
end
|
138
|
-
|
139
|
-
|
140
|
-
key.public_key = OpenSSL::PKey::EC::Point.new(
|
147
|
+
|
148
|
+
point = OpenSSL::PKey::EC::Point.new(
|
141
149
|
OpenSSL::PKey::EC::Group.new(curve_name),
|
142
150
|
OpenSSL::BN.new(['04' + x.unpack('H*').first + y.unpack('H*').first].pack('H*'), 2)
|
143
151
|
)
|
144
|
-
|
152
|
+
|
153
|
+
# Public key
|
154
|
+
data_sequence = OpenSSL::ASN1::Sequence([
|
155
|
+
OpenSSL::ASN1::Sequence([
|
156
|
+
OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
|
157
|
+
OpenSSL::ASN1::ObjectId(curve_name)
|
158
|
+
]),
|
159
|
+
OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed))
|
160
|
+
])
|
161
|
+
|
162
|
+
if d
|
163
|
+
# Private key
|
164
|
+
data_sequence = OpenSSL::ASN1::Sequence([
|
165
|
+
OpenSSL::ASN1::Integer(1),
|
166
|
+
OpenSSL::ASN1::OctetString(OpenSSL::BN.new(d, 2).to_s(2)),
|
167
|
+
OpenSSL::ASN1::ObjectId(curve_name, 0, :EXPLICIT),
|
168
|
+
OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed), 1, :EXPLICIT)
|
169
|
+
])
|
170
|
+
end
|
171
|
+
|
172
|
+
OpenSSL::PKey::EC.new(data_sequence.to_der)
|
145
173
|
end
|
146
174
|
end
|
147
175
|
end
|
data/lib/json/jws.rb
CHANGED
@@ -6,14 +6,14 @@ module JSON
|
|
6
6
|
|
7
7
|
NUM_OF_SEGMENTS = 3
|
8
8
|
|
9
|
-
|
9
|
+
attr_writer :signature_base_string
|
10
10
|
|
11
11
|
def initialize(jwt)
|
12
12
|
update jwt
|
13
13
|
end
|
14
14
|
|
15
15
|
def sign!(private_key_or_secret)
|
16
|
-
self.alg = autodetected_algorithm_from(private_key_or_secret) if
|
16
|
+
self.alg = autodetected_algorithm_from(private_key_or_secret) if alg == :autodetect
|
17
17
|
self.signature = sign signature_base_string, private_key_or_secret
|
18
18
|
self
|
19
19
|
end
|
@@ -43,31 +43,23 @@ module JSON
|
|
43
43
|
private
|
44
44
|
|
45
45
|
def digest
|
46
|
-
OpenSSL::Digest.new "SHA#{
|
46
|
+
OpenSSL::Digest.new "SHA#{alg.to_s[2, 3]}"
|
47
47
|
end
|
48
48
|
|
49
49
|
def hmac?
|
50
|
-
[:HS256, :HS384, :HS512].include?
|
50
|
+
[:HS256, :HS384, :HS512].include? alg&.to_sym
|
51
51
|
end
|
52
52
|
|
53
53
|
def rsa?
|
54
|
-
[:RS256, :RS384, :RS512].include?
|
54
|
+
[:RS256, :RS384, :RS512].include? alg&.to_sym
|
55
55
|
end
|
56
56
|
|
57
57
|
def rsa_pss?
|
58
|
-
|
59
|
-
if OpenSSL::VERSION < '2.1.0'
|
60
|
-
raise "#{alg} isn't supported. OpenSSL gem v2.1.0+ is required to use #{alg}."
|
61
|
-
else
|
62
|
-
true
|
63
|
-
end
|
64
|
-
else
|
65
|
-
false
|
66
|
-
end
|
58
|
+
[:PS256, :PS384, :PS512].include? alg&.to_sym
|
67
59
|
end
|
68
60
|
|
69
61
|
def ecdsa?
|
70
|
-
[:ES256, :ES384, :ES512].include?
|
62
|
+
[:ES256, :ES384, :ES512, :ES256K].include? alg&.to_sym
|
71
63
|
end
|
72
64
|
|
73
65
|
def autodetected_algorithm_from(private_key_or_secret)
|
@@ -85,6 +77,8 @@ module JSON
|
|
85
77
|
:ES384
|
86
78
|
when 'secp521r1'
|
87
79
|
:ES512
|
80
|
+
when 'secp256k1'
|
81
|
+
:ES256K
|
88
82
|
else
|
89
83
|
raise UnknownAlgorithm.new('Unknown EC Curve')
|
90
84
|
end
|
@@ -118,8 +112,7 @@ module JSON
|
|
118
112
|
private_key = private_key_or_secret
|
119
113
|
verify_ecdsa_group! private_key
|
120
114
|
asn1_to_raw(
|
121
|
-
private_key.
|
122
|
-
# private_key.sign(digest, signature_base_string), # NOTE: this causes `undefined method `private?'` error in ruby 2.3
|
115
|
+
private_key.sign(digest, signature_base_string),
|
123
116
|
private_key
|
124
117
|
)
|
125
118
|
else
|
@@ -152,14 +145,19 @@ module JSON
|
|
152
145
|
def verify_ecdsa_group!(key)
|
153
146
|
group_name = case digest.digest_length * 8
|
154
147
|
when 256
|
155
|
-
|
148
|
+
case key.group.curve_name
|
149
|
+
when 'secp256k1'
|
150
|
+
:secp256k1
|
151
|
+
else
|
152
|
+
:prime256v1
|
153
|
+
end
|
156
154
|
when 384
|
157
155
|
:secp384r1
|
158
156
|
when 512
|
159
157
|
:secp521r1
|
160
158
|
end
|
161
|
-
|
162
|
-
|
159
|
+
newkey = OpenSSL::PKey::EC.generate(group_name.to_s)
|
160
|
+
newkey.check_key
|
163
161
|
end
|
164
162
|
|
165
163
|
def raw_to_asn1(signature, public_key)
|
@@ -179,7 +177,7 @@ module JSON
|
|
179
177
|
unless input.count('.') + 1 == NUM_OF_SEGMENTS
|
180
178
|
raise InvalidFormat.new("Invalid JWS Format. JWS should include #{NUM_OF_SEGMENTS} segments.")
|
181
179
|
end
|
182
|
-
header, claims, signature = input.split('.',
|
180
|
+
header, claims, signature = input.split('.', NUM_OF_SEGMENTS).collect do |segment|
|
183
181
|
Base64.urlsafe_decode64 segment.to_s
|
184
182
|
end
|
185
183
|
header = JSON.parse(header).with_indifferent_access
|
@@ -191,7 +189,7 @@ module JSON
|
|
191
189
|
jws = new claims
|
192
190
|
jws.header = header
|
193
191
|
jws.signature = signature
|
194
|
-
jws.signature_base_string = input.split('.')[0,
|
192
|
+
jws.signature_base_string = input.split('.')[0, NUM_OF_SEGMENTS - 1].join('.')
|
195
193
|
jws.verify! public_key_or_secret, algorithms unless public_key_or_secret == :skip_verification
|
196
194
|
jws
|
197
195
|
end
|
data/lib/json/jwt.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
require 'openssl'
|
2
2
|
require 'base64'
|
3
|
+
require 'httpclient'
|
3
4
|
require 'active_support'
|
4
5
|
require 'active_support/core_ext'
|
5
6
|
require 'json/jose'
|
6
7
|
|
7
8
|
module JSON
|
8
9
|
class JWT < ActiveSupport::HashWithIndifferentAccess
|
10
|
+
VERSION = ::File.read(
|
11
|
+
::File.join(::File.dirname(__FILE__), '../../VERSION')
|
12
|
+
).chomp
|
13
|
+
|
9
14
|
attr_accessor :blank_payload
|
10
15
|
attr_accessor :signature
|
11
16
|
|
@@ -103,7 +108,11 @@ module JSON
|
|
103
108
|
when JWS::NUM_OF_SEGMENTS
|
104
109
|
JWS.decode_compact_serialized jwt_string, key_or_secret, algorithms, allow_blank_payload
|
105
110
|
when JWE::NUM_OF_SEGMENTS
|
106
|
-
|
111
|
+
if allow_blank_payload
|
112
|
+
raise InvalidFormat.new("JWE w/ blank payload is not supported.")
|
113
|
+
else
|
114
|
+
JWE.decode_compact_serialized jwt_string, key_or_secret, algorithms, encryption_methods
|
115
|
+
end
|
107
116
|
else
|
108
117
|
raise InvalidFormat.new("Invalid JWT Format. JWT should include #{JWS::NUM_OF_SEGMENTS} or #{JWE::NUM_OF_SEGMENTS} segments.")
|
109
118
|
end
|
@@ -132,3 +141,5 @@ require 'json/jwe'
|
|
132
141
|
require 'json/jwk'
|
133
142
|
require 'json/jwk/jwkizable'
|
134
143
|
require 'json/jwk/set'
|
144
|
+
require 'json/jwk/set/fetcher'
|
145
|
+
require 'json/jwk/set/fetcher/debugger/request_filter'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json-jwt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.15.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nov matake
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: httpclient
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +94,20 @@ dependencies:
|
|
80
94
|
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: webmock
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
83
111
|
- !ruby/object:Gem::Dependency
|
84
112
|
name: rspec
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -116,6 +144,8 @@ executables: []
|
|
116
144
|
extensions: []
|
117
145
|
extra_rdoc_files: []
|
118
146
|
files:
|
147
|
+
- ".github/FUNDING.yml"
|
148
|
+
- ".github/workflows/test_ruby.yml"
|
119
149
|
- ".gitignore"
|
120
150
|
- ".gitmodules"
|
121
151
|
- ".rspec"
|
@@ -131,13 +161,15 @@ files:
|
|
131
161
|
- lib/json/jwk.rb
|
132
162
|
- lib/json/jwk/jwkizable.rb
|
133
163
|
- lib/json/jwk/set.rb
|
164
|
+
- lib/json/jwk/set/fetcher.rb
|
165
|
+
- lib/json/jwk/set/fetcher/debugger/request_filter.rb
|
134
166
|
- lib/json/jws.rb
|
135
167
|
- lib/json/jwt.rb
|
136
168
|
homepage: https://github.com/nov/json-jwt
|
137
169
|
licenses:
|
138
170
|
- MIT
|
139
171
|
metadata: {}
|
140
|
-
post_install_message:
|
172
|
+
post_install_message:
|
141
173
|
rdoc_options: []
|
142
174
|
require_paths:
|
143
175
|
- lib
|
@@ -145,16 +177,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
145
177
|
requirements:
|
146
178
|
- - ">="
|
147
179
|
- !ruby/object:Gem::Version
|
148
|
-
version: '2.
|
180
|
+
version: '2.4'
|
149
181
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
182
|
requirements:
|
151
183
|
- - ">="
|
152
184
|
- !ruby/object:Gem::Version
|
153
185
|
version: '0'
|
154
186
|
requirements: []
|
155
|
-
|
156
|
-
|
157
|
-
signing_key:
|
187
|
+
rubygems_version: 3.5.3
|
188
|
+
signing_key:
|
158
189
|
specification_version: 4
|
159
190
|
summary: JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and
|
160
191
|
JSON Web Key) in Ruby
|