json-jwt 1.13.0 → 1.15.3

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: 0bc8f7f5b23b61360c4b6a72c253b52beb5f7226ebf441d6a6561729155ea55d
4
+ data.tar.gz: 7175e7ea9121d74d633bb32ce6f88e2d50ddbc3b0109426c562508e40a119727
5
5
  SHA512:
6
- metadata.gz: 90e611ff8e6f87f4b4008c15839008b0eaea3abf498e1d40dcfb875c99c7212d558d38ea5e93f74e3dcbfb4c0f05d29d712b8e64152179ccd02602b6ec79c8ca
7
- data.tar.gz: 82eb46ca549465d81027f9953f2cde953a582a7912e534a828b1114c78e1f469c9e03c9ebfb6b6609bddf11e1686defe10134fe287ed2b5768e05b8a3b53babf
6
+ metadata.gz: f169ddb8eafd2b66e84c8fd32328793e040477a376ab7dfedef29990d330afa667f5f563bc540a0479b095cc2c16cb38b6bb7a7a6c9842656ea41425e63c87b7
7
+ data.tar.gz: 53e010725185c4acab07988025b1dd70d7def52f27c285ed502a21f1d8e8ad1eedca780db14378824ff7891fbd852265b06a2256281c5a07d40545487ad9241c
@@ -0,0 +1,3 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: nov
@@ -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
@@ -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/.travis.yml CHANGED
@@ -3,9 +3,10 @@ before_install:
3
3
  - git submodule update --init --recursive
4
4
 
5
5
  rvm:
6
- - 2.5.8
7
- - 2.6.6
8
- - 2.7.1
6
+ - 2.6.10
7
+ - 2.7.6
8
+ - 3.0.4
9
+ - 3.1.2
9
10
 
10
11
  jdk:
11
12
  - openjdk11
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.13.0
1
+ 1.15.3
data/json-jwt.gemspec CHANGED
@@ -16,8 +16,10 @@ 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 '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
@@ -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
@@ -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
@@ -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,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
 
@@ -132,3 +137,5 @@ require 'json/jwe'
132
137
  require 'json/jwk'
133
138
  require 'json/jwk/jwkizable'
134
139
  require 'json/jwk/set'
140
+ require 'json/jwk/set/fetcher'
141
+ 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.13.0
4
+ version: 1.15.3
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-08-18 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
@@ -152,8 +184,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
184
  - !ruby/object:Gem::Version
153
185
  version: '0'
154
186
  requirements: []
155
- rubygems_version: 3.0.3
156
- signing_key:
187
+ rubygems_version: 3.1.6
188
+ signing_key:
157
189
  specification_version: 4
158
190
  summary: JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and
159
191
  JSON Web Key) in Ruby