json-jwt 1.13.0 → 1.16.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.
Potentially problematic release.
This version of json-jwt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +3 -0
- data/.github/workflows/spec.yml +32 -0
- data/.gitmodules +1 -1
- data/CHANGELOG.md +11 -0
- data/README.md +11 -2
- data/VERSION +1 -1
- data/json-jwt.gemspec +3 -0
- data/lib/json/jose.rb +1 -3
- data/lib/json/jwe.rb +14 -4
- data/lib/json/jwk/set/fetcher.rb +83 -0
- data/lib/json/jwk/set.rb +6 -0
- data/lib/json/jwk.rb +45 -19
- data/lib/json/jws.rb +2 -2
- data/lib/json/jwt.rb +7 -0
- metadata +52 -7
- data/.travis.yml +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0593ae4268dde10889b1e4272e01d7c95f2fdb2c69b365b81b67837b66d30531'
|
4
|
+
data.tar.gz: 27badbcb85bf47a663eed76b859cf0c7d502a0bb683a8f10ce9d8e3539a9149c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa6a607b44857bddb3f1f489c60cea213eaef6c4ab3481ffb3b665b21c4088bc7e12724bda2ca6c66d55cc2032cc392f85d08cabc6e774f5e8cb13bd62ec695d
|
7
|
+
data.tar.gz: c75bd449bb1e6d746e456ea2c58582cfff85a4d285f30d53e4b724f7904d13f626f84899034dffccdf4e9c41db0721b1573d968c45d2c123b1fb1e42e1379f8b
|
data/.github/FUNDING.yml
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
name: Spec
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
pull_request:
|
8
|
+
|
9
|
+
permissions:
|
10
|
+
contents: read
|
11
|
+
|
12
|
+
jobs:
|
13
|
+
spec:
|
14
|
+
strategy:
|
15
|
+
matrix:
|
16
|
+
os: ['ubuntu-20.04']
|
17
|
+
ruby-version: ['2.6', '2.7', '3.0', '3.1']
|
18
|
+
# ubuntu 22.04 only supports ssl 3 and thus only ruby 3.1
|
19
|
+
include:
|
20
|
+
- os: 'ubuntu-22.04'
|
21
|
+
ruby-version: '3.1'
|
22
|
+
runs-on: ${{ matrix.os }}
|
23
|
+
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v3
|
26
|
+
- name: Set up Ruby
|
27
|
+
uses: ruby/setup-ruby@v1
|
28
|
+
with:
|
29
|
+
ruby-version: ${{ matrix.ruby-version }}
|
30
|
+
bundler-cache: true
|
31
|
+
- name: Run Specs
|
32
|
+
run: bundle exec rake spec
|
data/.gitmodules
CHANGED
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and JSON Web Key) in Ruby
|
4
4
|
|
5
|
-
[](http://travis-ci.org/nov/json-jwt)
|
6
|
-
|
7
5
|
## Installation
|
8
6
|
|
9
7
|
```
|
@@ -49,6 +47,17 @@ input = "jwt_header.jwt_claims.jwt_signature"
|
|
49
47
|
JSON::JWT.decode(input, public_key)
|
50
48
|
```
|
51
49
|
|
50
|
+
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.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
# JWK Set Fetching & Caching
|
54
|
+
# NOTE: Optionally by setting cache instance, JWKs are cached by kid.
|
55
|
+
JSON::JWK::Set::Fetcher.cache = Rails.cache
|
56
|
+
|
57
|
+
JSON::JWK::Set::Fetcher.fetch(jwks_uri, kid: kid)
|
58
|
+
# => returns JSON::JWK instance or raise JSON::JWK::Set::KidNotFound
|
59
|
+
```
|
60
|
+
|
52
61
|
For more details, read [Documentation Wiki](https://github.com/nov/json-jwt/wiki).
|
53
62
|
|
54
63
|
## Note on Patches/Pull Requests
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.16.1
|
data/json-jwt.gemspec
CHANGED
@@ -16,8 +16,11 @@ Gem::Specification.new do |gem|
|
|
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 'faraday', '~> 2.0'
|
20
|
+
gem.add_runtime_dependency 'faraday-follow_redirects'
|
19
21
|
gem.add_development_dependency 'rake'
|
20
22
|
gem.add_development_dependency 'simplecov'
|
23
|
+
gem.add_development_dependency 'webmock'
|
21
24
|
gem.add_development_dependency 'rspec'
|
22
25
|
gem.add_development_dependency 'rspec-its'
|
23
26
|
end
|
data/lib/json/jose.rb
CHANGED
data/lib/json/jwe.rb
CHANGED
@@ -43,9 +43,12 @@ module JSON
|
|
43
43
|
raise UnexpectedAlgorithm.new('Unexpected alg header') unless algorithms.blank? || Array(algorithms).include?(alg)
|
44
44
|
raise UnexpectedAlgorithm.new('Unexpected enc header') unless encryption_methods.blank? || Array(encryption_methods).include?(enc)
|
45
45
|
self.private_key_or_secret = with_jwk_support private_key_or_secret
|
46
|
-
cipher.decrypt
|
47
46
|
self.content_encryption_key = decrypt_content_encryption_key
|
48
47
|
self.mac_key, self.encryption_key = derive_encryption_and_mac_keys
|
48
|
+
|
49
|
+
verify_cbc_authentication_tag! if cbc?
|
50
|
+
|
51
|
+
cipher.decrypt
|
49
52
|
cipher.key = encryption_key
|
50
53
|
cipher.iv = iv # NOTE: 'iv' has to be set after 'key' for GCM
|
51
54
|
if gcm?
|
@@ -54,8 +57,15 @@ module JSON
|
|
54
57
|
cipher.auth_tag = authentication_tag
|
55
58
|
cipher.auth_data = auth_data
|
56
59
|
end
|
57
|
-
|
58
|
-
|
60
|
+
|
61
|
+
begin
|
62
|
+
self.plain_text = cipher.update(cipher_text) + cipher.final
|
63
|
+
rescue OpenSSL::OpenSSLError
|
64
|
+
# Ensure that the same error is raised for invalid PKCS7 padding
|
65
|
+
# as for invalid signatures. This prevents padding-oracle attacks.
|
66
|
+
raise DecryptionFailed
|
67
|
+
end
|
68
|
+
|
59
69
|
self
|
60
70
|
end
|
61
71
|
|
@@ -244,7 +254,7 @@ module JSON
|
|
244
254
|
sha_digest, mac_key, secured_input
|
245
255
|
)[0, sha_size / 2 / 8]
|
246
256
|
unless secure_compare(authentication_tag, expected_authentication_tag)
|
247
|
-
raise DecryptionFailed
|
257
|
+
raise DecryptionFailed
|
248
258
|
end
|
249
259
|
end
|
250
260
|
|
@@ -0,0 +1,83 @@
|
|
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
|
+
Faraday.new(headers: {user_agent: "JSON::JWK::Set::Fetcher #{VERSION}"}) do |faraday|
|
40
|
+
faraday.response :raise_error
|
41
|
+
faraday.response :follow_redirects
|
42
|
+
faraday.response :logger, JSON::JWK::Set::Fetcher.logger if debugging?
|
43
|
+
faraday.adapter Faraday.default_adapter
|
44
|
+
http_config.try(:call, faraday)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
def self.http_config(&block)
|
48
|
+
@@http_config ||= block
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.cache=(cache)
|
52
|
+
@@cache = cache
|
53
|
+
end
|
54
|
+
def self.cache
|
55
|
+
@@cache
|
56
|
+
end
|
57
|
+
self.cache = Cache.new
|
58
|
+
|
59
|
+
def self.fetch(jwks_uri, kid:, auto_detect: true, **options)
|
60
|
+
cache_key = [
|
61
|
+
'json:jwk:set',
|
62
|
+
OpenSSL::Digest::MD5.hexdigest(jwks_uri),
|
63
|
+
kid
|
64
|
+
].collect(&:to_s).join(':')
|
65
|
+
|
66
|
+
jwks = Set.new(
|
67
|
+
JSON.parse(
|
68
|
+
cache.fetch(cache_key, options) do
|
69
|
+
http_client.get(jwks_uri).body
|
70
|
+
end
|
71
|
+
)
|
72
|
+
)
|
73
|
+
|
74
|
+
if auto_detect
|
75
|
+
jwks[kid] or raise KidNotFound
|
76
|
+
else
|
77
|
+
jwks
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
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
@@ -101,22 +101,29 @@ module JSON
|
|
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
|
@@ -137,13 +144,32 @@ module JSON
|
|
137
144
|
Base64.urlsafe_decode64(self[key])
|
138
145
|
end
|
139
146
|
end
|
140
|
-
|
141
|
-
|
142
|
-
key.public_key = OpenSSL::PKey::EC::Point.new(
|
147
|
+
|
148
|
+
point = OpenSSL::PKey::EC::Point.new(
|
143
149
|
OpenSSL::PKey::EC::Group.new(curve_name),
|
144
150
|
OpenSSL::BN.new(['04' + x.unpack('H*').first + y.unpack('H*').first].pack('H*'), 2)
|
145
151
|
)
|
146
|
-
|
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)
|
147
173
|
end
|
148
174
|
end
|
149
175
|
end
|
data/lib/json/jws.rb
CHANGED
@@ -156,8 +156,8 @@ module JSON
|
|
156
156
|
when 512
|
157
157
|
:secp521r1
|
158
158
|
end
|
159
|
-
|
160
|
-
|
159
|
+
newkey = OpenSSL::PKey::EC.generate(group_name.to_s)
|
160
|
+
newkey.check_key
|
161
161
|
end
|
162
162
|
|
163
163
|
def raw_to_asn1(signature, public_key)
|
data/lib/json/jwt.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
require 'openssl'
|
2
2
|
require 'base64'
|
3
|
+
require 'faraday'
|
4
|
+
require 'faraday/follow_redirects'
|
3
5
|
require 'active_support'
|
4
6
|
require 'active_support/core_ext'
|
5
7
|
require 'json/jose'
|
6
8
|
|
7
9
|
module JSON
|
8
10
|
class JWT < ActiveSupport::HashWithIndifferentAccess
|
11
|
+
VERSION = ::File.read(
|
12
|
+
::File.join(::File.dirname(__FILE__), '../../VERSION')
|
13
|
+
).chomp
|
14
|
+
|
9
15
|
attr_accessor :blank_payload
|
10
16
|
attr_accessor :signature
|
11
17
|
|
@@ -132,3 +138,4 @@ require 'json/jwe'
|
|
132
138
|
require 'json/jwk'
|
133
139
|
require 'json/jwk/jwkizable'
|
134
140
|
require 'json/jwk/set'
|
141
|
+
require 'json/jwk/set/fetcher'
|
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.16.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: 2022-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -52,6 +52,34 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: faraday
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: faraday-follow_redirects
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: rake
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +108,20 @@ dependencies:
|
|
80
108
|
- - ">="
|
81
109
|
- !ruby/object:Gem::Version
|
82
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: webmock
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
83
125
|
- !ruby/object:Gem::Dependency
|
84
126
|
name: rspec
|
85
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -116,10 +158,12 @@ executables: []
|
|
116
158
|
extensions: []
|
117
159
|
extra_rdoc_files: []
|
118
160
|
files:
|
161
|
+
- ".github/FUNDING.yml"
|
162
|
+
- ".github/workflows/spec.yml"
|
119
163
|
- ".gitignore"
|
120
164
|
- ".gitmodules"
|
121
165
|
- ".rspec"
|
122
|
-
-
|
166
|
+
- CHANGELOG.md
|
123
167
|
- Gemfile
|
124
168
|
- LICENSE
|
125
169
|
- README.md
|
@@ -131,13 +175,14 @@ files:
|
|
131
175
|
- lib/json/jwk.rb
|
132
176
|
- lib/json/jwk/jwkizable.rb
|
133
177
|
- lib/json/jwk/set.rb
|
178
|
+
- lib/json/jwk/set/fetcher.rb
|
134
179
|
- lib/json/jws.rb
|
135
180
|
- lib/json/jwt.rb
|
136
181
|
homepage: https://github.com/nov/json-jwt
|
137
182
|
licenses:
|
138
183
|
- MIT
|
139
184
|
metadata: {}
|
140
|
-
post_install_message:
|
185
|
+
post_install_message:
|
141
186
|
rdoc_options: []
|
142
187
|
require_paths:
|
143
188
|
- lib
|
@@ -152,8 +197,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
197
|
- !ruby/object:Gem::Version
|
153
198
|
version: '0'
|
154
199
|
requirements: []
|
155
|
-
rubygems_version: 3.
|
156
|
-
signing_key:
|
200
|
+
rubygems_version: 3.3.7
|
201
|
+
signing_key:
|
157
202
|
specification_version: 4
|
158
203
|
summary: JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and
|
159
204
|
JSON Web Key) in Ruby
|