json-jwt 1.13.0 → 1.16.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/.github/FUNDING.yml +3 -0
- data/.github/workflows/spec.yml +32 -0
- data/.gitmodules +1 -1
- 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/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 +48 -4
- 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: 2097e754332fbc0d82af414efcce07c63da2bbd7cc3f2976a8df1c770dffb9b8
|
|
4
|
+
data.tar.gz: a7a9950a0501b58b249bb39d2c369ea315cd40d4f9297b6e19f66d82763ec2ce
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a0092471b468de8a24909cafa45a86c934ee67c0eedf40ae962427f72007d038e1a2dde5a1d32c39465e9594b0c06e634bed8f8bade183a7919f5a12222ee916
|
|
7
|
+
data.tar.gz: 5b5ff6abbd60b781b7d9d291153a80f83a108fe37d9358dfac8463ff810b0016c5224f849baac3a4720d0bdc8b6d8bbdc0131780b8fba29c6e4d49c72fa2c034
|
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/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.0
|
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
|
@@ -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.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- nov matake
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-10-08 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,11 @@ 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"
|
|
123
166
|
- Gemfile
|
|
124
167
|
- LICENSE
|
|
125
168
|
- README.md
|
|
@@ -131,6 +174,7 @@ files:
|
|
|
131
174
|
- lib/json/jwk.rb
|
|
132
175
|
- lib/json/jwk/jwkizable.rb
|
|
133
176
|
- lib/json/jwk/set.rb
|
|
177
|
+
- lib/json/jwk/set/fetcher.rb
|
|
134
178
|
- lib/json/jws.rb
|
|
135
179
|
- lib/json/jwt.rb
|
|
136
180
|
homepage: https://github.com/nov/json-jwt
|
|
@@ -152,7 +196,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
152
196
|
- !ruby/object:Gem::Version
|
|
153
197
|
version: '0'
|
|
154
198
|
requirements: []
|
|
155
|
-
rubygems_version: 3.
|
|
199
|
+
rubygems_version: 3.1.6
|
|
156
200
|
signing_key:
|
|
157
201
|
specification_version: 4
|
|
158
202
|
summary: JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and
|