jwt 2.4.1 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +14 -13
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +21 -2
- data/README.md +66 -27
- data/lib/jwt/algos/eddsa.rb +2 -0
- data/lib/jwt/base64.rb +19 -0
- data/lib/jwt/configuration/container.rb +21 -0
- data/lib/jwt/configuration/decode_configuration.rb +46 -0
- data/lib/jwt/configuration/jwk_configuration.rb +27 -0
- data/lib/jwt/configuration.rb +15 -0
- data/lib/jwt/decode.rb +4 -6
- data/lib/jwt/encode.rb +2 -2
- data/lib/jwt/jwk/ec.rb +91 -46
- data/lib/jwt/jwk/hmac.rb +19 -10
- data/lib/jwt/jwk/key_base.rb +23 -7
- data/lib/jwt/jwk/key_finder.rb +1 -1
- data/lib/jwt/jwk/kid_as_key_digest.rb +15 -0
- data/lib/jwt/jwk/rsa.rb +54 -32
- data/lib/jwt/jwk/thumbprint.rb +26 -0
- data/lib/jwt/version.rb +7 -2
- data/lib/jwt/x5c_key_finder.rb +1 -1
- data/lib/jwt.rb +5 -4
- metadata +11 -5
- data/lib/jwt/default_options.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3098671a837e7b291103cde1921277c61ecaa0f0797b955e6adc65328498f0d
|
4
|
+
data.tar.gz: 3253833ac6d7743e40a5d5157b161cd0daecc9b77f61dfa7687d6b3da1be56ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 306c946b1199301a3f1000c8ffba4a77d07fd05dd83f769da86fd29f254827b5af8488a4b6a54b11f1f7f3a028cb88caafb7ed67528e7004c0337f6506e595ea
|
7
|
+
data.tar.gz: 57d1eba7a06bc9d9f9fcb76b42aa3808415af5020c53969b4cada890b1646e7d348a96ce18010ab0a978e42825febbeb7b3f205b72e8ce60ef90132cf5887599
|
data/.github/workflows/test.yml
CHANGED
@@ -13,7 +13,7 @@ jobs:
|
|
13
13
|
timeout-minutes: 30
|
14
14
|
runs-on: ubuntu-latest
|
15
15
|
steps:
|
16
|
-
- uses: actions/checkout@
|
16
|
+
- uses: actions/checkout@v3
|
17
17
|
- name: Set up Ruby
|
18
18
|
uses: ruby/setup-ruby@v1
|
19
19
|
with:
|
@@ -22,34 +22,35 @@ jobs:
|
|
22
22
|
- name: Run RuboCop
|
23
23
|
run: bundle exec rubocop
|
24
24
|
test:
|
25
|
+
name: ${{ matrix.os }} - Ruby ${{ matrix.ruby }}
|
26
|
+
runs-on: ${{ matrix.os }}
|
25
27
|
strategy:
|
26
28
|
fail-fast: false
|
27
29
|
matrix:
|
30
|
+
os:
|
31
|
+
- ubuntu-20.04
|
28
32
|
ruby:
|
29
|
-
- 2.5
|
30
|
-
- 2.6
|
31
|
-
- 2.7
|
33
|
+
- "2.5"
|
34
|
+
- "2.6"
|
35
|
+
- "2.7"
|
32
36
|
- "3.0"
|
33
|
-
- 3.1
|
37
|
+
- "3.1"
|
34
38
|
gemfile:
|
35
39
|
- gemfiles/standalone.gemfile
|
36
40
|
- gemfiles/openssl.gemfile
|
37
41
|
- gemfiles/rbnacl.gemfile
|
38
42
|
experimental: [false]
|
39
43
|
include:
|
40
|
-
- ruby: 2.7
|
41
|
-
|
42
|
-
- ruby: "
|
43
|
-
|
44
|
-
- ruby: "truffleruby-head"
|
45
|
-
experimental: true
|
46
|
-
runs-on: ubuntu-20.04
|
44
|
+
- { os: ubuntu-20.04, ruby: "2.7", gemfile: 'gemfiles/rbnacl.gemfile', experimental: false }
|
45
|
+
- { os: ubuntu-22.04, ruby: "3.1", experimental: false }
|
46
|
+
- { os: ubuntu-20.04, ruby: "truffleruby-head", experimental: true }
|
47
|
+
- { os: ubuntu-22.04, ruby: "head", experimental: true }
|
47
48
|
continue-on-error: ${{ matrix.experimental }}
|
48
49
|
env:
|
49
50
|
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
|
50
51
|
|
51
52
|
steps:
|
52
|
-
- uses: actions/checkout@
|
53
|
+
- uses: actions/checkout@v3
|
53
54
|
|
54
55
|
- name: Install libsodium
|
55
56
|
run: |
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,11 +1,30 @@
|
|
1
1
|
# Changelog
|
2
|
-
|
2
|
+
|
3
|
+
|
4
|
+
## [v2.5.0](https://github.com/jwt/ruby-jwt/tree/v2.5.0) (NEXT)
|
5
|
+
|
6
|
+
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.4.1...master)
|
7
|
+
|
8
|
+
**Features:**
|
9
|
+
|
10
|
+
- Support JWK thumbprints as key ids [#481](https://github.com/jwt/ruby-jwt/pull/481) ([@anakinj](https://github.com/anakinj)).
|
11
|
+
- Your contribution here
|
3
12
|
|
4
13
|
**Fixes and enhancements:**
|
5
|
-
-
|
14
|
+
- Bring back the old Base64 (RFC2045) deocode mechanisms [#488](https://github.com/jwt/ruby-jwt/pull/488) ([@anakinj](https://github.com/anakinj)).
|
15
|
+
- Rescue RbNaCl exception for EdDSA wrong key [#491](https://github.com/jwt/ruby-jwt/pull/491) ([@n-studio](https://github.com/n-studio)).
|
16
|
+
- New parameter name for cases when kid is not found using JWK key loader proc [#501](https://github.com/jwt/ruby-jwt/pull/501) ([@anakinj](https://github.com/anakinj)).
|
17
|
+
- Fix NoMethodError when a 2 segment token is missing 'alg' header [#502](https://github.com/jwt/ruby-jwt/pull/502) ([@cmrd-senya](https://github.com/cmrd-senya)).
|
18
|
+
- Support OpenSSL >= 3.0 [#496](https://github.com/jwt/ruby-jwt/pull/496) ([@anakinj](https://github.com/anakinj)).
|
19
|
+
- Your contribution here
|
20
|
+
|
21
|
+
## [v2.4.1](https://github.com/jwt/ruby-jwt/tree/v2.4.1) (2022-06-07)
|
6
22
|
|
7
23
|
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.4.0...v2.4.1)
|
8
24
|
|
25
|
+
**Fixes and enhancements:**
|
26
|
+
- Raise JWT::DecodeError on invalid signature [\#484](https://github.com/jwt/ruby-jwt/pull/484) ([@freakyfelt!](https://github.com/freakyfelt!)).
|
27
|
+
|
9
28
|
## [v2.4.0](https://github.com/jwt/ruby-jwt/tree/v2.4.0) (2022-06-06)
|
10
29
|
|
11
30
|
[Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.3.0...v2.4.0)
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ A ruby implementation of the [RFC 7519 OAuth JSON Web Token (JWT)](https://tools
|
|
12
12
|
If you have further questions related to development or usage, join us: [ruby-jwt google group](https://groups.google.com/forum/#!forum/ruby-jwt).
|
13
13
|
|
14
14
|
## Announcements
|
15
|
-
* Ruby 2.4 support
|
15
|
+
* Ruby 2.4 support was dropped in version 2.4.0
|
16
16
|
* Ruby 1.9.3 support was dropped at December 31st, 2016.
|
17
17
|
* Version 1.5.3 yanked. See: [#132](https://github.com/jwt/ruby-jwt/issues/132) and [#133](https://github.com/jwt/ruby-jwt/issues/133)
|
18
18
|
|
@@ -135,17 +135,14 @@ puts decoded_token
|
|
135
135
|
* ES256K - ECDSA using P-256K and SHA-256
|
136
136
|
|
137
137
|
```ruby
|
138
|
-
ecdsa_key = OpenSSL::PKey::EC.
|
139
|
-
ecdsa_key.generate_key
|
140
|
-
ecdsa_public = OpenSSL::PKey::EC.new ecdsa_key
|
141
|
-
ecdsa_public.private_key = nil
|
138
|
+
ecdsa_key = OpenSSL::PKey::EC.generate('prime256v1')
|
142
139
|
|
143
140
|
token = JWT.encode payload, ecdsa_key, 'ES256'
|
144
141
|
|
145
142
|
# eyJhbGciOiJFUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.AlLW--kaF7EX1NMX9WJRuIW8NeRJbn2BLXHns7Q5TZr7Hy3lF6MOpMlp7GoxBFRLISQ6KrD0CJOrR8aogEsPeg
|
146
143
|
puts token
|
147
144
|
|
148
|
-
decoded_token = JWT.decode token,
|
145
|
+
decoded_token = JWT.decode token, ecdsa_key, true, { algorithm: 'ES256' }
|
149
146
|
|
150
147
|
# Array
|
151
148
|
# [
|
@@ -186,7 +183,7 @@ decoded_token = JWT.decode token, public_key, true, { algorithm: 'ED25519' }
|
|
186
183
|
|
187
184
|
### **RSASSA-PSS**
|
188
185
|
|
189
|
-
In order to use this algorithm you need to add the `openssl` gem to
|
186
|
+
In order to use this algorithm you need to add the `openssl` gem to your `Gemfile` with a version greater or equal to `2.1`.
|
190
187
|
|
191
188
|
```ruby
|
192
189
|
gem 'openssl', '~> 2.1'
|
@@ -546,30 +543,41 @@ end
|
|
546
543
|
|
547
544
|
### JSON Web Key (JWK)
|
548
545
|
|
549
|
-
JWK is a JSON structure representing a cryptographic key. Currently only supports RSA, EC and HMAC keys.
|
546
|
+
JWK is a JSON structure representing a cryptographic key. Currently only supports RSA, EC and HMAC keys. The `jwks` option can be given as a lambda that evaluates every time a kid is resolved.
|
550
547
|
|
551
|
-
|
552
|
-
jwk = JWT::JWK.new(OpenSSL::PKey::RSA.new(2048), "optional-kid")
|
553
|
-
payload, headers = { data: 'data' }, { kid: jwk.kid }
|
554
|
-
|
555
|
-
token = JWT.encode(payload, jwk.keypair, 'RS512', headers)
|
548
|
+
If the kid is not found from the given set the loader will be called a second time with the `kid_not_found` option set to `true`. The application can choose to implement some kind of JWK cache invalidation or other mechanism to handle such cases.
|
556
549
|
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
550
|
+
```ruby
|
551
|
+
jwk = JWT::JWK.new(OpenSSL::PKey::RSA.new(2048), 'optional-kid')
|
552
|
+
payload = { data: 'data' }
|
553
|
+
headers = { kid: jwk.kid }
|
554
|
+
|
555
|
+
token = JWT.encode(payload, jwk.keypair, 'RS512', headers)
|
556
|
+
|
557
|
+
# The jwk loader would fetch the set of JWKs from a trusted source,
|
558
|
+
# to avoid malicious requests triggering cache invalidations there needs to be some kind of grace time or other logic for determining the validity of the invalidation.
|
559
|
+
# This example only allows cache invalidations every 5 minutes.
|
560
|
+
jwk_loader = ->(options) do
|
561
|
+
if options[:kid_not_found] && @cache_last_update < Time.now.to_i - 300
|
562
|
+
logger.info("Invalidating JWK cache. #{options[:kid]} not found from previous cache")
|
563
|
+
@cached_keys = nil
|
564
|
+
end
|
565
|
+
@cached_keys ||= begin
|
566
|
+
@cache_last_update = Time.now.to_i
|
567
|
+
{ keys: [jwk.export] }
|
568
|
+
end
|
569
|
+
end
|
562
570
|
|
563
|
-
begin
|
564
|
-
|
565
|
-
rescue JWT::JWKError
|
566
|
-
|
567
|
-
rescue JWT::DecodeError
|
568
|
-
|
569
|
-
end
|
571
|
+
begin
|
572
|
+
JWT.decode(token, nil, true, { algorithms: ['RS512'], jwks: jwk_loader })
|
573
|
+
rescue JWT::JWKError
|
574
|
+
# Handle problems with the provided JWKs
|
575
|
+
rescue JWT::DecodeError
|
576
|
+
# Handle other decode related issues e.g. no kid in header, no matching public key found etc.
|
577
|
+
end
|
570
578
|
```
|
571
579
|
|
572
|
-
or by passing
|
580
|
+
or by passing the JWKs as a simple Hash
|
573
581
|
|
574
582
|
```
|
575
583
|
jwks = { keys: [{ ... }] } # keys accepts both of string and symbol
|
@@ -587,8 +595,39 @@ jwk_hash = jwk.export
|
|
587
595
|
jwk_hash_with_private_key = jwk.export(include_private: true)
|
588
596
|
```
|
589
597
|
|
590
|
-
|
598
|
+
### Key ID (kid) and JWKs
|
599
|
+
|
600
|
+
The key id (kid) generation in the gem is a custom algorithm and not based on any standards. To use a standardized JWK thumbprint (RFC 7638) as the kid for JWKs a generator type can be specified in the global configuration or can be given to the JWK instance on initialization.
|
601
|
+
|
602
|
+
```ruby
|
603
|
+
JWT.configuration.jwk.kid_generator_type = :rfc7638_thumbprint
|
604
|
+
# OR
|
605
|
+
JWT.configuration.jwk.kid_generator = ::JWT::JWK::Thumbprint
|
606
|
+
# OR
|
607
|
+
jwk = JWT::JWK.new(OpenSSL::PKey::RSA.new(2048), kid_generator: ::JWT::JWK::Thumbprint)
|
608
|
+
|
609
|
+
jwk_hash = jwk.export
|
610
|
+
|
611
|
+
thumbprint_as_the_kid = jwk_hash[:kid]
|
612
|
+
|
613
|
+
```
|
614
|
+
|
615
|
+
# Development and Tests
|
616
|
+
|
617
|
+
We depend on [Bundler](http://rubygems.org/gems/bundler) for defining gemspec and performing releases to rubygems.org, which can be done with
|
618
|
+
|
619
|
+
```bash
|
620
|
+
rake release
|
621
|
+
```
|
591
622
|
|
623
|
+
The tests are written with rspec. [Appraisal](https://github.com/thoughtbot/appraisal) is used to ensure compatibility with 3rd party dependencies providing cryptographic features.
|
624
|
+
|
625
|
+
```bash
|
626
|
+
bundle install
|
627
|
+
bundle exec appraisal rake test
|
628
|
+
```
|
629
|
+
|
630
|
+
## How to contribute
|
592
631
|
See [CONTRIBUTING](CONTRIBUTING.md).
|
593
632
|
|
594
633
|
## Contributors
|
data/lib/jwt/algos/eddsa.rb
CHANGED
@@ -27,6 +27,8 @@ module JWT
|
|
27
27
|
raise DecodeError, "key given is a #{public_key.class} but has to be a RbNaCl::Signatures::Ed25519::VerifyKey" if public_key.class != RbNaCl::Signatures::Ed25519::VerifyKey
|
28
28
|
|
29
29
|
public_key.verify(signature, signing_input)
|
30
|
+
rescue RbNaCl::CryptoError
|
31
|
+
false
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
data/lib/jwt/base64.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
module JWT
|
6
|
+
# Base64 helpers
|
7
|
+
class Base64
|
8
|
+
class << self
|
9
|
+
def url_encode(str)
|
10
|
+
::Base64.encode64(str).tr('+/', '-_').gsub(/[\n=]/, '')
|
11
|
+
end
|
12
|
+
|
13
|
+
def url_decode(str)
|
14
|
+
str += '=' * (4 - str.length.modulo(4))
|
15
|
+
::Base64.decode64(str.tr('-_', '+/'))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'decode_configuration'
|
4
|
+
require_relative 'jwk_configuration'
|
5
|
+
|
6
|
+
module JWT
|
7
|
+
module Configuration
|
8
|
+
class Container
|
9
|
+
attr_accessor :decode, :jwk
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
reset!
|
13
|
+
end
|
14
|
+
|
15
|
+
def reset!
|
16
|
+
@decode = DecodeConfiguration.new
|
17
|
+
@jwk = JwkConfiguration.new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JWT
|
4
|
+
module Configuration
|
5
|
+
class DecodeConfiguration
|
6
|
+
attr_accessor :verify_expiration,
|
7
|
+
:verify_not_before,
|
8
|
+
:verify_iss,
|
9
|
+
:verify_iat,
|
10
|
+
:verify_jti,
|
11
|
+
:verify_aud,
|
12
|
+
:verify_sub,
|
13
|
+
:leeway,
|
14
|
+
:algorithms,
|
15
|
+
:required_claims
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@verify_expiration = true
|
19
|
+
@verify_not_before = true
|
20
|
+
@verify_iss = false
|
21
|
+
@verify_iat = false
|
22
|
+
@verify_jti = false
|
23
|
+
@verify_aud = false
|
24
|
+
@verify_sub = false
|
25
|
+
@leeway = 0
|
26
|
+
@algorithms = ['HS256']
|
27
|
+
@required_claims = []
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_h
|
31
|
+
{
|
32
|
+
verify_expiration: verify_expiration,
|
33
|
+
verify_not_before: verify_not_before,
|
34
|
+
verify_iss: verify_iss,
|
35
|
+
verify_iat: verify_iat,
|
36
|
+
verify_jti: verify_jti,
|
37
|
+
verify_aud: verify_aud,
|
38
|
+
verify_sub: verify_sub,
|
39
|
+
leeway: leeway,
|
40
|
+
algorithms: algorithms,
|
41
|
+
required_claims: required_claims
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../jwk/kid_as_key_digest'
|
4
|
+
require_relative '../jwk/thumbprint'
|
5
|
+
|
6
|
+
module JWT
|
7
|
+
module Configuration
|
8
|
+
class JwkConfiguration
|
9
|
+
def initialize
|
10
|
+
self.kid_generator_type = :key_digest
|
11
|
+
end
|
12
|
+
|
13
|
+
def kid_generator_type=(value)
|
14
|
+
self.kid_generator = case value
|
15
|
+
when :key_digest
|
16
|
+
JWT::JWK::KidAsKeyDigest
|
17
|
+
when :rfc7638_thumbprint
|
18
|
+
JWT::JWK::Thumbprint
|
19
|
+
else
|
20
|
+
raise ArgumentError, "#{value} is not a valid kid generator type."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_accessor :kid_generator
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'configuration/container'
|
4
|
+
|
5
|
+
module JWT
|
6
|
+
module Configuration
|
7
|
+
def configure
|
8
|
+
yield(configuration)
|
9
|
+
end
|
10
|
+
|
11
|
+
def configuration
|
12
|
+
@configuration ||= ::JWT::Configuration::Container.new
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/jwt/decode.rb
CHANGED
@@ -113,13 +113,11 @@ module JWT
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def none_algorithm?
|
116
|
-
algorithm
|
116
|
+
algorithm == 'none'
|
117
117
|
end
|
118
118
|
|
119
119
|
def decode_crypto
|
120
|
-
@signature = Base64.
|
121
|
-
rescue ArgumentError
|
122
|
-
raise(JWT::DecodeError, 'Invalid segment encoding')
|
120
|
+
@signature = ::JWT::Base64.url_decode(@segments[2] || '')
|
123
121
|
end
|
124
122
|
|
125
123
|
def algorithm
|
@@ -139,8 +137,8 @@ module JWT
|
|
139
137
|
end
|
140
138
|
|
141
139
|
def parse_and_decode(segment)
|
142
|
-
JWT::JSON.parse(Base64.
|
143
|
-
rescue ::JSON::ParserError
|
140
|
+
JWT::JSON.parse(::JWT::Base64.url_decode(segment))
|
141
|
+
rescue ::JSON::ParserError
|
144
142
|
raise JWT::DecodeError, 'Invalid segment encoding'
|
145
143
|
end
|
146
144
|
end
|
data/lib/jwt/encode.rb
CHANGED
@@ -55,11 +55,11 @@ module JWT
|
|
55
55
|
def encode_signature
|
56
56
|
return '' if @algorithm == ALG_NONE
|
57
57
|
|
58
|
-
Base64.
|
58
|
+
::JWT::Base64.url_encode(JWT::Signature.sign(@algorithm, encoded_header_and_payload, @key))
|
59
59
|
end
|
60
60
|
|
61
61
|
def encode(data)
|
62
|
-
Base64.
|
62
|
+
::JWT::Base64.url_encode(JWT::JSON.generate(data))
|
63
63
|
end
|
64
64
|
|
65
65
|
def combine(*parts)
|
data/lib/jwt/jwk/ec.rb
CHANGED
@@ -4,39 +4,53 @@ require 'forwardable'
|
|
4
4
|
|
5
5
|
module JWT
|
6
6
|
module JWK
|
7
|
-
class EC < KeyBase
|
7
|
+
class EC < KeyBase # rubocop:disable Metrics/ClassLength
|
8
8
|
extend Forwardable
|
9
|
-
def_delegators
|
9
|
+
def_delegators :keypair, :public_key
|
10
10
|
|
11
11
|
KTY = 'EC'
|
12
12
|
KTYS = [KTY, OpenSSL::PKey::EC].freeze
|
13
13
|
BINARY = 2
|
14
14
|
|
15
|
-
|
15
|
+
attr_reader :keypair
|
16
|
+
|
17
|
+
def initialize(keypair, options = {})
|
16
18
|
raise ArgumentError, 'keypair must be of type OpenSSL::PKey::EC' unless keypair.is_a?(OpenSSL::PKey::EC)
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
+
@keypair = keypair
|
21
|
+
|
22
|
+
super(options)
|
20
23
|
end
|
21
24
|
|
22
25
|
def private?
|
23
26
|
@keypair.private_key?
|
24
27
|
end
|
25
28
|
|
26
|
-
def
|
29
|
+
def members
|
27
30
|
crv, x_octets, y_octets = keypair_components(keypair)
|
28
|
-
|
31
|
+
{
|
29
32
|
kty: KTY,
|
30
33
|
crv: crv,
|
31
34
|
x: encode_octets(x_octets),
|
32
|
-
y: encode_octets(y_octets)
|
33
|
-
kid: kid
|
35
|
+
y: encode_octets(y_octets)
|
34
36
|
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def export(options = {})
|
40
|
+
exported_hash = members.merge(kid: kid)
|
41
|
+
|
35
42
|
return exported_hash unless private? && options[:include_private] == true
|
36
43
|
|
37
44
|
append_private_parts(exported_hash)
|
38
45
|
end
|
39
46
|
|
47
|
+
def key_digest
|
48
|
+
_crv, x_octets, y_octets = keypair_components(keypair)
|
49
|
+
sequence = OpenSSL::ASN1::Sequence([OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(x_octets, BINARY)),
|
50
|
+
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(y_octets, BINARY))])
|
51
|
+
OpenSSL::Digest::SHA256.hexdigest(sequence.to_der)
|
52
|
+
end
|
53
|
+
|
40
54
|
private
|
41
55
|
|
42
56
|
def append_private_parts(the_hash)
|
@@ -46,13 +60,6 @@ module JWT
|
|
46
60
|
)
|
47
61
|
end
|
48
62
|
|
49
|
-
def generate_kid(ec_keypair)
|
50
|
-
_crv, x_octets, y_octets = keypair_components(ec_keypair)
|
51
|
-
sequence = OpenSSL::ASN1::Sequence([OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(x_octets, BINARY)),
|
52
|
-
OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(y_octets, BINARY))])
|
53
|
-
OpenSSL::Digest::SHA256.hexdigest(sequence.to_der)
|
54
|
-
end
|
55
|
-
|
56
63
|
def keypair_components(ec_keypair)
|
57
64
|
encoded_point = ec_keypair.public_key.to_bn.to_s(BINARY)
|
58
65
|
case ec_keypair.group.curve_name
|
@@ -75,11 +82,11 @@ module JWT
|
|
75
82
|
end
|
76
83
|
|
77
84
|
def encode_octets(octets)
|
78
|
-
Base64.
|
85
|
+
::JWT::Base64.url_encode(octets)
|
79
86
|
end
|
80
87
|
|
81
88
|
def encode_open_ssl_bn(key_part)
|
82
|
-
Base64.
|
89
|
+
::JWT::Base64.url_encode(key_part.to_s(BINARY))
|
83
90
|
end
|
84
91
|
|
85
92
|
class << self
|
@@ -90,7 +97,7 @@ module JWT
|
|
90
97
|
jwk_crv, jwk_x, jwk_y, jwk_d, jwk_kid = jwk_attrs(jwk_data, %i[crv x y d kid])
|
91
98
|
raise JWT::JWKError, 'Key format is invalid for EC' unless jwk_crv && jwk_x && jwk_y
|
92
99
|
|
93
|
-
new(ec_pkey(jwk_crv, jwk_x, jwk_y, jwk_d), jwk_kid)
|
100
|
+
new(ec_pkey(jwk_crv, jwk_x, jwk_y, jwk_d), kid: jwk_kid)
|
94
101
|
end
|
95
102
|
|
96
103
|
def to_openssl_curve(crv)
|
@@ -114,39 +121,77 @@ module JWT
|
|
114
121
|
end
|
115
122
|
end
|
116
123
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
124
|
+
if ::JWT.openssl_3?
|
125
|
+
def ec_pkey(jwk_crv, jwk_x, jwk_y, jwk_d) # rubocop:disable Metrics/MethodLength
|
126
|
+
curve = to_openssl_curve(jwk_crv)
|
127
|
+
|
128
|
+
x_octets = decode_octets(jwk_x)
|
129
|
+
y_octets = decode_octets(jwk_y)
|
130
|
+
|
131
|
+
point = OpenSSL::PKey::EC::Point.new(
|
132
|
+
OpenSSL::PKey::EC::Group.new(curve),
|
133
|
+
OpenSSL::BN.new([0x04, x_octets, y_octets].pack('Ca*a*'), 2)
|
134
|
+
)
|
135
|
+
|
136
|
+
sequence = if jwk_d
|
137
|
+
# https://datatracker.ietf.org/doc/html/rfc5915.html
|
138
|
+
# ECPrivateKey ::= SEQUENCE {
|
139
|
+
# version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
|
140
|
+
# privateKey OCTET STRING,
|
141
|
+
# parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
|
142
|
+
# publicKey [1] BIT STRING OPTIONAL
|
143
|
+
# }
|
144
|
+
|
145
|
+
OpenSSL::ASN1::Sequence([
|
146
|
+
OpenSSL::ASN1::Integer(1),
|
147
|
+
OpenSSL::ASN1::OctetString(OpenSSL::BN.new(decode_octets(jwk_d), 2).to_s(2)),
|
148
|
+
OpenSSL::ASN1::ObjectId(curve, 0, :EXPLICIT),
|
149
|
+
OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed), 1, :EXPLICIT)
|
150
|
+
])
|
151
|
+
else
|
152
|
+
OpenSSL::ASN1::Sequence([
|
153
|
+
OpenSSL::ASN1::Sequence([OpenSSL::ASN1::ObjectId('id-ecPublicKey'), OpenSSL::ASN1::ObjectId(curve)]),
|
154
|
+
OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed))
|
155
|
+
])
|
156
|
+
end
|
157
|
+
|
158
|
+
OpenSSL::PKey::EC.new(sequence.to_der)
|
159
|
+
end
|
160
|
+
else
|
161
|
+
def ec_pkey(jwk_crv, jwk_x, jwk_y, jwk_d)
|
162
|
+
curve = to_openssl_curve(jwk_crv)
|
163
|
+
|
164
|
+
x_octets = decode_octets(jwk_x)
|
165
|
+
y_octets = decode_octets(jwk_y)
|
166
|
+
|
167
|
+
key = OpenSSL::PKey::EC.new(curve)
|
168
|
+
|
169
|
+
# The details of the `Point` instantiation are covered in:
|
170
|
+
# - https://docs.ruby-lang.org/en/2.4.0/OpenSSL/PKey/EC.html
|
171
|
+
# - https://www.openssl.org/docs/manmaster/man3/EC_POINT_new.html
|
172
|
+
# - https://tools.ietf.org/html/rfc5480#section-2.2
|
173
|
+
# - https://www.secg.org/SEC1-Ver-1.0.pdf
|
174
|
+
# Section 2.3.3 of the last of these references specifies that the
|
175
|
+
# encoding of an uncompressed point consists of the byte `0x04` followed
|
176
|
+
# by the x value then the y value.
|
177
|
+
point = OpenSSL::PKey::EC::Point.new(
|
178
|
+
OpenSSL::PKey::EC::Group.new(curve),
|
179
|
+
OpenSSL::BN.new([0x04, x_octets, y_octets].pack('Ca*a*'), 2)
|
180
|
+
)
|
181
|
+
|
182
|
+
key.public_key = point
|
183
|
+
key.private_key = OpenSSL::BN.new(decode_octets(jwk_d), 2) if jwk_d
|
184
|
+
|
185
|
+
key
|
186
|
+
end
|
142
187
|
end
|
143
188
|
|
144
189
|
def decode_octets(jwk_data)
|
145
|
-
Base64.
|
190
|
+
::JWT::Base64.url_decode(jwk_data)
|
146
191
|
end
|
147
192
|
|
148
193
|
def decode_open_ssl_bn(jwk_data)
|
149
|
-
OpenSSL::BN.new(Base64.
|
194
|
+
OpenSSL::BN.new(::JWT::Base64.url_decode(jwk_data), BINARY)
|
150
195
|
end
|
151
196
|
end
|
152
197
|
end
|
data/lib/jwt/jwk/hmac.rb
CHANGED
@@ -3,14 +3,16 @@
|
|
3
3
|
module JWT
|
4
4
|
module JWK
|
5
5
|
class HMAC < KeyBase
|
6
|
-
KTY
|
6
|
+
KTY = 'oct'
|
7
7
|
KTYS = [KTY, String].freeze
|
8
8
|
|
9
|
-
|
10
|
-
raise ArgumentError, 'keypair must be of type String' unless keypair.is_a?(String)
|
9
|
+
attr_reader :signing_key
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
def initialize(signing_key, options = {})
|
12
|
+
raise ArgumentError, 'signing_key must be of type String' unless signing_key.is_a?(String)
|
13
|
+
|
14
|
+
@signing_key = signing_key
|
15
|
+
super(options)
|
14
16
|
end
|
15
17
|
|
16
18
|
def private?
|
@@ -31,14 +33,21 @@ module JWT
|
|
31
33
|
return exported_hash unless private? && options[:include_private] == true
|
32
34
|
|
33
35
|
exported_hash.merge(
|
34
|
-
k:
|
36
|
+
k: signing_key
|
35
37
|
)
|
36
38
|
end
|
37
39
|
|
38
|
-
|
40
|
+
def members
|
41
|
+
{
|
42
|
+
kty: KTY,
|
43
|
+
k: signing_key
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
alias keypair signing_key # for backwards compatibility
|
39
48
|
|
40
|
-
def
|
41
|
-
sequence = OpenSSL::ASN1::Sequence([OpenSSL::ASN1::UTF8String.new(
|
49
|
+
def key_digest
|
50
|
+
sequence = OpenSSL::ASN1::Sequence([OpenSSL::ASN1::UTF8String.new(signing_key),
|
42
51
|
OpenSSL::ASN1::UTF8String.new(KTY)])
|
43
52
|
OpenSSL::Digest::SHA256.hexdigest(sequence.to_der)
|
44
53
|
end
|
@@ -50,7 +59,7 @@ module JWT
|
|
50
59
|
|
51
60
|
raise JWT::JWKError, 'Key format is invalid for HMAC' unless jwk_k
|
52
61
|
|
53
|
-
new(jwk_k, jwk_kid)
|
62
|
+
new(jwk_k, kid: jwk_kid)
|
54
63
|
end
|
55
64
|
end
|
56
65
|
end
|
data/lib/jwt/jwk/key_base.rb
CHANGED
@@ -3,17 +3,33 @@
|
|
3
3
|
module JWT
|
4
4
|
module JWK
|
5
5
|
class KeyBase
|
6
|
-
attr_reader :keypair, :kid
|
7
|
-
|
8
|
-
def initialize(keypair, kid = nil)
|
9
|
-
@keypair = keypair
|
10
|
-
@kid = kid
|
11
|
-
end
|
12
|
-
|
13
6
|
def self.inherited(klass)
|
14
7
|
super
|
15
8
|
::JWT::JWK.classes << klass
|
16
9
|
end
|
10
|
+
|
11
|
+
def initialize(options)
|
12
|
+
options ||= {}
|
13
|
+
|
14
|
+
if options.is_a?(String) # For backwards compatibility when kid was a String
|
15
|
+
options = { kid: options }
|
16
|
+
end
|
17
|
+
|
18
|
+
@kid = options[:kid]
|
19
|
+
@kid_generator = options[:kid_generator] || ::JWT.configuration.jwk.kid_generator
|
20
|
+
end
|
21
|
+
|
22
|
+
def kid
|
23
|
+
@kid ||= generate_kid
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :kid_generator
|
29
|
+
|
30
|
+
def generate_kid
|
31
|
+
kid_generator.new(self).generate
|
32
|
+
end
|
17
33
|
end
|
18
34
|
end
|
19
35
|
end
|
data/lib/jwt/jwk/key_finder.rb
CHANGED
data/lib/jwt/jwk/rsa.rb
CHANGED
@@ -8,10 +8,14 @@ module JWT
|
|
8
8
|
KTYS = [KTY, OpenSSL::PKey::RSA].freeze
|
9
9
|
RSA_KEY_ELEMENTS = %i[n e d p q dp dq qi].freeze
|
10
10
|
|
11
|
-
|
11
|
+
attr_reader :keypair
|
12
|
+
|
13
|
+
def initialize(keypair, options = {})
|
12
14
|
raise ArgumentError, 'keypair must be of type OpenSSL::PKey::RSA' unless keypair.is_a?(OpenSSL::PKey::RSA)
|
13
15
|
|
14
|
-
|
16
|
+
@keypair = keypair
|
17
|
+
|
18
|
+
super(options)
|
15
19
|
end
|
16
20
|
|
17
21
|
def private?
|
@@ -23,26 +27,29 @@ module JWT
|
|
23
27
|
end
|
24
28
|
|
25
29
|
def export(options = {})
|
26
|
-
exported_hash =
|
27
|
-
kty: KTY,
|
28
|
-
n: encode_open_ssl_bn(public_key.n),
|
29
|
-
e: encode_open_ssl_bn(public_key.e),
|
30
|
-
kid: kid
|
31
|
-
}
|
30
|
+
exported_hash = members.merge(kid: kid)
|
32
31
|
|
33
32
|
return exported_hash unless private? && options[:include_private] == true
|
34
33
|
|
35
34
|
append_private_parts(exported_hash)
|
36
35
|
end
|
37
36
|
|
38
|
-
|
37
|
+
def members
|
38
|
+
{
|
39
|
+
kty: KTY,
|
40
|
+
n: encode_open_ssl_bn(public_key.n),
|
41
|
+
e: encode_open_ssl_bn(public_key.e)
|
42
|
+
}
|
43
|
+
end
|
39
44
|
|
40
|
-
def
|
45
|
+
def key_digest
|
41
46
|
sequence = OpenSSL::ASN1::Sequence([OpenSSL::ASN1::Integer.new(public_key.n),
|
42
47
|
OpenSSL::ASN1::Integer.new(public_key.e)])
|
43
48
|
OpenSSL::Digest::SHA256.hexdigest(sequence.to_der)
|
44
49
|
end
|
45
50
|
|
51
|
+
private
|
52
|
+
|
46
53
|
def append_private_parts(the_hash)
|
47
54
|
the_hash.merge(
|
48
55
|
d: encode_open_ssl_bn(keypair.d),
|
@@ -55,7 +62,7 @@ module JWT
|
|
55
62
|
end
|
56
63
|
|
57
64
|
def encode_open_ssl_bn(key_part)
|
58
|
-
Base64.
|
65
|
+
::JWT::Base64.url_encode(key_part.to_s(BINARY))
|
59
66
|
end
|
60
67
|
|
61
68
|
class << self
|
@@ -63,8 +70,7 @@ module JWT
|
|
63
70
|
pkey_params = jwk_attributes(jwk_data, *RSA_KEY_ELEMENTS) do |value|
|
64
71
|
decode_open_ssl_bn(value)
|
65
72
|
end
|
66
|
-
kid
|
67
|
-
new(rsa_pkey(pkey_params), kid)
|
73
|
+
new(rsa_pkey(pkey_params), kid: jwk_attributes(jwk_data, :kid)[:kid])
|
68
74
|
end
|
69
75
|
|
70
76
|
private
|
@@ -80,35 +86,51 @@ module JWT
|
|
80
86
|
def rsa_pkey(rsa_parameters)
|
81
87
|
raise JWT::JWKError, 'Key format is invalid for RSA' unless rsa_parameters[:n] && rsa_parameters[:e]
|
82
88
|
|
83
|
-
|
89
|
+
create_rsa_key(rsa_parameters)
|
84
90
|
end
|
85
91
|
|
86
|
-
if
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
+
if ::JWT.openssl_3?
|
93
|
+
ASN1_SEQUENCE = %i[n e d p q dp dq qi].freeze
|
94
|
+
def create_rsa_key(rsa_parameters)
|
95
|
+
sequence = ASN1_SEQUENCE.each_with_object([]) do |key, arr|
|
96
|
+
next if rsa_parameters[key].nil?
|
97
|
+
|
98
|
+
arr << OpenSSL::ASN1::Integer.new(rsa_parameters[key])
|
99
|
+
end
|
100
|
+
|
101
|
+
if sequence.size > 2 # For a private key
|
102
|
+
sequence.unshift(OpenSSL::ASN1::Integer.new(0))
|
103
|
+
end
|
104
|
+
|
105
|
+
OpenSSL::PKey::RSA.new(OpenSSL::ASN1::Sequence(sequence).to_der)
|
106
|
+
end
|
107
|
+
elsif OpenSSL::PKey::RSA.new.respond_to?(:set_key)
|
108
|
+
def create_rsa_key(rsa_parameters)
|
109
|
+
OpenSSL::PKey::RSA.new.tap do |rsa_key|
|
110
|
+
rsa_key.set_key(rsa_parameters[:n], rsa_parameters[:e], rsa_parameters[:d])
|
111
|
+
rsa_key.set_factors(rsa_parameters[:p], rsa_parameters[:q]) if rsa_parameters[:p] && rsa_parameters[:q]
|
112
|
+
rsa_key.set_crt_params(rsa_parameters[:dp], rsa_parameters[:dq], rsa_parameters[:qi]) if rsa_parameters[:dp] && rsa_parameters[:dq] && rsa_parameters[:qi]
|
113
|
+
end
|
92
114
|
end
|
93
115
|
else
|
94
|
-
def
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
116
|
+
def create_rsa_key(rsa_parameters) # rubocop:disable Metrics/AbcSize
|
117
|
+
OpenSSL::PKey::RSA.new.tap do |rsa_key|
|
118
|
+
rsa_key.n = rsa_parameters[:n]
|
119
|
+
rsa_key.e = rsa_parameters[:e]
|
120
|
+
rsa_key.d = rsa_parameters[:d] if rsa_parameters[:d]
|
121
|
+
rsa_key.p = rsa_parameters[:p] if rsa_parameters[:p]
|
122
|
+
rsa_key.q = rsa_parameters[:q] if rsa_parameters[:q]
|
123
|
+
rsa_key.dmp1 = rsa_parameters[:dp] if rsa_parameters[:dp]
|
124
|
+
rsa_key.dmq1 = rsa_parameters[:dq] if rsa_parameters[:dq]
|
125
|
+
rsa_key.iqmp = rsa_parameters[:qi] if rsa_parameters[:qi]
|
126
|
+
end
|
105
127
|
end
|
106
128
|
end
|
107
129
|
|
108
130
|
def decode_open_ssl_bn(jwk_data)
|
109
131
|
return nil unless jwk_data
|
110
132
|
|
111
|
-
OpenSSL::BN.new(Base64.
|
133
|
+
OpenSSL::BN.new(::JWT::Base64.url_decode(jwk_data), BINARY)
|
112
134
|
end
|
113
135
|
end
|
114
136
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JWT
|
4
|
+
module JWK
|
5
|
+
# https://tools.ietf.org/html/rfc7638
|
6
|
+
class Thumbprint
|
7
|
+
attr_reader :jwk
|
8
|
+
|
9
|
+
def initialize(jwk)
|
10
|
+
@jwk = jwk
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate
|
14
|
+
::Base64.urlsafe_encode64(
|
15
|
+
Digest::SHA256.digest(
|
16
|
+
JWT::JSON.generate(
|
17
|
+
jwk.members.sort.to_h
|
18
|
+
)
|
19
|
+
), padding: false
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
alias to_s generate
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/jwt/version.rb
CHANGED
@@ -11,13 +11,18 @@ module JWT
|
|
11
11
|
# major version
|
12
12
|
MAJOR = 2
|
13
13
|
# minor version
|
14
|
-
MINOR =
|
14
|
+
MINOR = 5
|
15
15
|
# tiny version
|
16
|
-
TINY =
|
16
|
+
TINY = 0
|
17
17
|
# alpha, beta, etc. tag
|
18
18
|
PRE = nil
|
19
19
|
|
20
20
|
# Build version string
|
21
21
|
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
22
22
|
end
|
23
|
+
|
24
|
+
def self.openssl_3?
|
25
|
+
return false if OpenSSL::OPENSSL_VERSION.include?('LibreSSL')
|
26
|
+
return true if OpenSSL::OPENSSL_VERSION_NUMBER >= 3 * 0x10000000
|
27
|
+
end
|
23
28
|
end
|
data/lib/jwt/x5c_key_finder.rb
CHANGED
data/lib/jwt.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'jwt/version'
|
4
|
+
require 'jwt/base64'
|
4
5
|
require 'jwt/json'
|
5
6
|
require 'jwt/decode'
|
6
|
-
require 'jwt/
|
7
|
+
require 'jwt/configuration'
|
7
8
|
require 'jwt/encode'
|
8
9
|
require 'jwt/error'
|
9
10
|
require 'jwt/jwk'
|
@@ -13,7 +14,7 @@ require 'jwt/jwk'
|
|
13
14
|
# Should be up to date with the latest spec:
|
14
15
|
# https://tools.ietf.org/html/rfc7519
|
15
16
|
module JWT
|
16
|
-
|
17
|
+
extend ::JWT::Configuration
|
17
18
|
|
18
19
|
module_function
|
19
20
|
|
@@ -25,6 +26,6 @@ module JWT
|
|
25
26
|
end
|
26
27
|
|
27
28
|
def decode(jwt, key = nil, verify = true, options = {}, &keyfinder) # rubocop:disable Style/OptionalBooleanParameter
|
28
|
-
Decode.new(jwt, key, verify,
|
29
|
+
Decode.new(jwt, key, verify, configuration.decode.to_h.merge(options), &keyfinder).decode_segments
|
29
30
|
end
|
30
31
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jwt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Rudat
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: appraisal
|
@@ -127,9 +127,13 @@ files:
|
|
127
127
|
- lib/jwt/algos/ps.rb
|
128
128
|
- lib/jwt/algos/rsa.rb
|
129
129
|
- lib/jwt/algos/unsupported.rb
|
130
|
+
- lib/jwt/base64.rb
|
130
131
|
- lib/jwt/claims_validator.rb
|
132
|
+
- lib/jwt/configuration.rb
|
133
|
+
- lib/jwt/configuration/container.rb
|
134
|
+
- lib/jwt/configuration/decode_configuration.rb
|
135
|
+
- lib/jwt/configuration/jwk_configuration.rb
|
131
136
|
- lib/jwt/decode.rb
|
132
|
-
- lib/jwt/default_options.rb
|
133
137
|
- lib/jwt/encode.rb
|
134
138
|
- lib/jwt/error.rb
|
135
139
|
- lib/jwt/json.rb
|
@@ -138,7 +142,9 @@ files:
|
|
138
142
|
- lib/jwt/jwk/hmac.rb
|
139
143
|
- lib/jwt/jwk/key_base.rb
|
140
144
|
- lib/jwt/jwk/key_finder.rb
|
145
|
+
- lib/jwt/jwk/kid_as_key_digest.rb
|
141
146
|
- lib/jwt/jwk/rsa.rb
|
147
|
+
- lib/jwt/jwk/thumbprint.rb
|
142
148
|
- lib/jwt/security_utils.rb
|
143
149
|
- lib/jwt/signature.rb
|
144
150
|
- lib/jwt/verify.rb
|
@@ -150,7 +156,7 @@ licenses:
|
|
150
156
|
- MIT
|
151
157
|
metadata:
|
152
158
|
bug_tracker_uri: https://github.com/jwt/ruby-jwt/issues
|
153
|
-
changelog_uri: https://github.com/jwt/ruby-jwt/blob/v2.
|
159
|
+
changelog_uri: https://github.com/jwt/ruby-jwt/blob/v2.5.0/CHANGELOG.md
|
154
160
|
post_install_message:
|
155
161
|
rdoc_options: []
|
156
162
|
require_paths:
|
@@ -166,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
166
172
|
- !ruby/object:Gem::Version
|
167
173
|
version: '0'
|
168
174
|
requirements: []
|
169
|
-
rubygems_version: 3.3.
|
175
|
+
rubygems_version: 3.3.21
|
170
176
|
signing_key:
|
171
177
|
specification_version: 4
|
172
178
|
summary: JSON Web Token implementation in Ruby
|
data/lib/jwt/default_options.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module JWT
|
4
|
-
module DefaultOptions
|
5
|
-
DEFAULT_OPTIONS = {
|
6
|
-
verify_expiration: true,
|
7
|
-
verify_not_before: true,
|
8
|
-
verify_iss: false,
|
9
|
-
verify_iat: false,
|
10
|
-
verify_jti: false,
|
11
|
-
verify_aud: false,
|
12
|
-
verify_sub: false,
|
13
|
-
leeway: 0,
|
14
|
-
algorithms: ['HS256'],
|
15
|
-
required_claims: []
|
16
|
-
}.freeze
|
17
|
-
end
|
18
|
-
end
|