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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e18796342211bf21448b9bb5b43749894717bc0a270ae7e1679efbbaa387fc4b
4
- data.tar.gz: 19b56b26f69a78d2b3ac842865571b973426006b371674ebb6f19cfaf9156385
3
+ metadata.gz: '0593ae4268dde10889b1e4272e01d7c95f2fdb2c69b365b81b67837b66d30531'
4
+ data.tar.gz: 27badbcb85bf47a663eed76b859cf0c7d502a0bb683a8f10ce9d8e3539a9149c
5
5
  SHA512:
6
- metadata.gz: 90e611ff8e6f87f4b4008c15839008b0eaea3abf498e1d40dcfb875c99c7212d558d38ea5e93f74e3dcbfb4c0f05d29d712b8e64152179ccd02602b6ec79c8ca
7
- data.tar.gz: 82eb46ca549465d81027f9953f2cde953a582a7912e534a828b1114c78e1f469c9e03c9ebfb6b6609bddf11e1686defe10134fe287ed2b5768e05b8a3b53babf
6
+ metadata.gz: aa6a607b44857bddb3f1f489c60cea213eaef6c4ab3481ffb3b665b21c4088bc7e12724bda2ca6c66d55cc2032cc392f85d08cabc6e774f5e8cb13bd62ec695d
7
+ data.tar.gz: c75bd449bb1e6d746e456ea2c58582cfff85a4d285f30d53e4b724f7904d13f626f84899034dffccdf4e9c41db0721b1573d968c45d2c123b1fb1e42e1379f8b
@@ -0,0 +1,3 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: nov
@@ -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
@@ -1,3 +1,3 @@
1
1
  [submodule "spec/helpers/json-jwt-nimbus"]
2
2
  path = spec/helpers/json-jwt-nimbus
3
- url = git://github.com/nov/json-jwt-nimbus.git
3
+ url = https://github.com/nov/json-jwt-nimbus.git
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ ## [Unreleased]
2
+
3
+ ## [1.16.0] - 2022-10-08
4
+
5
+ ### Added
6
+
7
+ - start recording CHANGELOG
8
+
9
+ ### Changed
10
+
11
+ * Switch from httpclient to faraday v2 https://github.com/nov/json-jwt/pull/110
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
- [![Build Status](https://secure.travis-ci.org/nov/json-jwt.png)](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.13.0
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
@@ -26,9 +26,7 @@ module JSON
26
26
  when JSON::JWK
27
27
  key.to_key
28
28
  when JSON::JWK::Set
29
- key.detect do |jwk|
30
- jwk[:kid] && jwk[:kid] == kid
31
- end&.to_key or raise JWK::Set::KidNotFound
29
+ key[kid]&.to_key or raise JWK::Set::KidNotFound
32
30
  else
33
31
  key
34
32
  end
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
- self.plain_text = cipher.update(cipher_text) + cipher.final
58
- verify_cbc_authentication_tag! if cbc?
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.new('Invalid authentication tag')
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
- key = OpenSSL::PKey::RSA.new
105
- if key.respond_to? :set_key
106
- key.set_key n, e, d
107
- key.set_factors p, q if p && q
108
- key.set_crt_params dp, dq, qi if dp && dq && qi
109
- else
110
- key.e = e
111
- key.n = n
112
- key.d = d if d
113
- key.p = p if p
114
- key.q = q if q
115
- key.dmp1 = dp if dp
116
- key.dmq1 = dq if dq
117
- key.iqmp = qi if qi
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
- key
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
- key = OpenSSL::PKey::EC.new curve_name
141
- key.private_key = OpenSSL::BN.new(d, 2) if d
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
- key
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
- key.group = OpenSSL::PKey::EC::Group.new group_name.to_s
160
- key.check_key
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.13.0
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: 2020-05-31 00:00:00.000000000 Z
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
- - ".travis.yml"
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.0.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
data/.travis.yml DELETED
@@ -1,11 +0,0 @@
1
- before_install:
2
- - gem install bundler
3
- - git submodule update --init --recursive
4
-
5
- rvm:
6
- - 2.5.8
7
- - 2.6.6
8
- - 2.7.1
9
-
10
- jdk:
11
- - openjdk11