doorkeeper-jwt 0.4.4 → 0.4.5
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/dependabot.yml +5 -0
- data/.github/workflows/changelog.yml +3 -3
- data/.github/workflows/ci.yml +25 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +7 -0
- data/Gemfile +1 -1
- data/README.md +82 -1
- data/doorkeeper-jwt.gemspec +3 -1
- data/lib/doorkeeper/jwt/config.rb +2 -1
- data/lib/doorkeeper/jwt/errors.rb +12 -0
- data/lib/doorkeeper/jwt/version.rb +1 -1
- data/lib/doorkeeper/jwt.rb +61 -44
- metadata +5 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 51843843df19db6ed75ac9500ba810ab9e5ccde882386ced00d0746933ccd4c7
|
|
4
|
+
data.tar.gz: 982167d24d8e64f959fde2a1b89ffa11a513a02136a4147dd64ecacca2536ffb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2dad7626a80e34c5cea0cfd69c1b48d94db47a2748eccefa9d4e3f462a054865e28e518af1da1836008d7cecbaa16ebf2c122d934f3d75f7762879300fad3e40
|
|
7
|
+
data.tar.gz: d191d7577852ae158b2c54fb4cfe530e3e0f383dea8b1bde0ccdf528dc2489b9458811709ed2e09a3e818eaeaf5ec773d192e50296d88918e9e43bb2dfb0e506
|
data/.github/dependabot.yml
CHANGED
|
@@ -16,10 +16,10 @@ jobs:
|
|
|
16
16
|
changelog:
|
|
17
17
|
runs-on: ubuntu-latest
|
|
18
18
|
steps:
|
|
19
|
-
- uses: actions/checkout@v7
|
|
19
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
20
20
|
- name: Check changed paths
|
|
21
21
|
id: changes
|
|
22
|
-
uses: dorny/paths-filter@v4
|
|
22
|
+
uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
|
|
23
23
|
with:
|
|
24
24
|
filters: |
|
|
25
25
|
gem_changes:
|
|
@@ -34,7 +34,7 @@ jobs:
|
|
|
34
34
|
- name: Enforce changelog
|
|
35
35
|
if: |
|
|
36
36
|
steps.changes.outputs.gem_changes == 'true'
|
|
37
|
-
uses: dangoslen/changelog-enforcer@v3
|
|
37
|
+
uses: dangoslen/changelog-enforcer@8b5e9dc3121363bb7c0115f8533404d92af382de # v3.7.0
|
|
38
38
|
with:
|
|
39
39
|
changeLogPath: CHANGELOG.md
|
|
40
40
|
skipLabels: "dependencies"
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -23,8 +23,10 @@ jobs:
|
|
|
23
23
|
experimental: [false]
|
|
24
24
|
os: [ ubuntu-latest ]
|
|
25
25
|
ruby:
|
|
26
|
-
- '3.
|
|
27
|
-
- '3.
|
|
26
|
+
- '3.2'
|
|
27
|
+
- '3.3'
|
|
28
|
+
- '3.4'
|
|
29
|
+
- '4.0'
|
|
28
30
|
# The minimum declared in the gemspec and the latest release. 5.4 is the oldest
|
|
29
31
|
# version whose options DSL resolves against our own config builder.
|
|
30
32
|
doorkeeper:
|
|
@@ -32,10 +34,10 @@ jobs:
|
|
|
32
34
|
- 'latest'
|
|
33
35
|
steps:
|
|
34
36
|
- name: Repo checkout
|
|
35
|
-
uses: actions/checkout@
|
|
37
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
36
38
|
|
|
37
39
|
- name: Setup Ruby
|
|
38
|
-
uses: ruby/setup-ruby@v1
|
|
40
|
+
uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
|
|
39
41
|
with:
|
|
40
42
|
ruby-version: ${{ matrix.ruby }}
|
|
41
43
|
bundler-cache: true
|
|
@@ -45,3 +47,22 @@ jobs:
|
|
|
45
47
|
- name: Run tests
|
|
46
48
|
timeout-minutes: 10
|
|
47
49
|
run: bundle exec rake test
|
|
50
|
+
|
|
51
|
+
- name: Upload coverage to Coveralls
|
|
52
|
+
uses: coverallsapp/github-action@8d6379e14d29928660c4ba802d8e85393440b329 # v2.3.8
|
|
53
|
+
with:
|
|
54
|
+
file: coverage/.resultset.json
|
|
55
|
+
format: simplecov
|
|
56
|
+
flag-name: ruby-${{ matrix.ruby }}-doorkeeper-${{ matrix.doorkeeper }}
|
|
57
|
+
parallel: true
|
|
58
|
+
|
|
59
|
+
coverage:
|
|
60
|
+
name: Coveralls Finished
|
|
61
|
+
needs: build
|
|
62
|
+
if: always()
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
steps:
|
|
65
|
+
- name: Coveralls Finished
|
|
66
|
+
uses: coverallsapp/github-action@8d6379e14d29928660c4ba802d8e85393440b329 # v2.3.8
|
|
67
|
+
with:
|
|
68
|
+
parallel-finished: true
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,13 @@ project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
8
8
|
|
|
9
9
|
- Add your entry here
|
|
10
10
|
|
|
11
|
+
# [0.4.5] - 2026-09-16
|
|
12
|
+
|
|
13
|
+
- **Security**: Raise `Doorkeeper::JWT::SigningMethodMissing` instead of issuing an unsigned (`alg: none`) JWT when a signing key is configured but `signing_method` is not. Issuing unsigned tokens with no signing key at all now warns and will become an error in a future release
|
|
14
|
+
- Add `required_ruby_version >= 3.2` to the gemspec and update the CI matrix to 3.2, 3.3, 3.4 and 4.0, aligning with doorkeeper core
|
|
15
|
+
- Allow `signing_method`, `secret_key` and `secret_key_path` to be configured with a block evaluated per token [#66](https://github.com/doorkeeper-gem/doorkeeper-jwt/pull/66)
|
|
16
|
+
- Fix broken Coveralls tests coverage [#67](https://github.com/doorkeeper-gem/doorkeeper-jwt/pull/67)
|
|
17
|
+
|
|
11
18
|
# [0.4.4] - 2026-08-21
|
|
12
19
|
|
|
13
20
|
- Fix `[DOORKEEPER] Option ... already defined and will be overridden` warnings on gem load [#61](https://github.com/doorkeeper-gem/doorkeeper-jwt/pull/61)
|
data/Gemfile
CHANGED
|
@@ -11,6 +11,6 @@ gemspec
|
|
|
11
11
|
doorkeeper_version = ENV.fetch("DOORKEEPER_VERSION", "latest")
|
|
12
12
|
gem "doorkeeper", doorkeeper_version unless doorkeeper_version == "latest"
|
|
13
13
|
|
|
14
|
-
gem "
|
|
14
|
+
gem "simplecov", "~> 1.1", require: false
|
|
15
15
|
gem "rubocop", "~> 1.8", require: false
|
|
16
16
|
gem "rubocop-rspec", "~> 3.0", require: false
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[](https://rubygems.org/gems/doorkeeper-jwt)
|
|
2
2
|
[](https://coveralls.io/github/doorkeeper-gem/doorkeeper-jwt?branch=master)
|
|
3
3
|
[](https://github.com/doorkeeper-gem/doorkeeper-jwt/actions/workflows/ci.yml)
|
|
4
|
-
[](https://qlty.sh/gh/doorkeeper-gem/projects/doorkeeper-jwt)
|
|
5
5
|
|
|
6
6
|
# Doorkeeper::JWT
|
|
7
7
|
|
|
@@ -103,6 +103,87 @@ Doorkeeper::JWT.configure do
|
|
|
103
103
|
end
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
+
### Authenticating more than one model
|
|
107
|
+
|
|
108
|
+
`opts[:resource_owner_id]` alone does not tell the payload block which model the token belongs to, so an application
|
|
109
|
+
with several resource owner models (say, `Driver` and `Client`) cannot look the owner up from the id.
|
|
110
|
+
|
|
111
|
+
Doorkeeper 5.4 and newer can hand the owner record itself to the generator. Run the generator, which enables
|
|
112
|
+
`use_polymorphic_resource_owner` in the `Doorkeeper.configure` block and creates the migration that adds the
|
|
113
|
+
`resource_owner_type` columns, then apply the migration:
|
|
114
|
+
|
|
115
|
+
$ rails generate doorkeeper:enable_polymorphic_resource_owner
|
|
116
|
+
$ rails db:migrate
|
|
117
|
+
|
|
118
|
+
The payload block then receives the record as `opts[:resource_owner]`, so the payload can branch on its class:
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
Doorkeeper::JWT.configure do
|
|
122
|
+
token_payload do |opts|
|
|
123
|
+
owner = opts[:resource_owner]
|
|
124
|
+
|
|
125
|
+
# client credentials tokens have no resource owner
|
|
126
|
+
next { sub: opts[:application]&.uid } unless owner
|
|
127
|
+
|
|
128
|
+
# ids are only unique per model, so include the model name in `sub`
|
|
129
|
+
{
|
|
130
|
+
sub: "#{owner.class.name.underscore}:#{owner.id}",
|
|
131
|
+
owner_type: owner.class.name,
|
|
132
|
+
email: owner.email
|
|
133
|
+
}
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Tokens issued by the client credentials flow have no resource owner, so `opts[:resource_owner]` is `nil` there.
|
|
139
|
+
|
|
140
|
+
### Using more than one signing method
|
|
141
|
+
|
|
142
|
+
`signing_method`, `secret_key` and `secret_key_path` also accept a block. The block receives the same
|
|
143
|
+
options hash as `token_payload` (`resource_owner_id`, `application`, `scopes`, ...) and is evaluated
|
|
144
|
+
whenever the option is needed for the token being generated, so you can pick the algorithm and the key
|
|
145
|
+
per request — for example an RSA-signed token for clients with an `admin` scope and an HMAC-signed token
|
|
146
|
+
for everyone else:
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
Doorkeeper::JWT.configure do
|
|
150
|
+
signing_method do |opts|
|
|
151
|
+
opts[:scopes].exists?('admin') ? :rs512 : :hs256
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
secret_key do |opts|
|
|
155
|
+
opts[:scopes].exists?('admin') ? ENV['JWT_RSA_PRIVATE_KEY'] : ENV['JWT_HMAC_SECRET']
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Doorkeeper hands `opts[:scopes]` over as a `Doorkeeper::OAuth::Scopes`, so match a single scope with
|
|
161
|
+
`exists?` rather than with a substring check: `opts[:scopes].to_s.include?('admin')` would also be true for
|
|
162
|
+
an unrelated `superadmin` or `admin_readonly` scope, and picking a signing key that way is easy to get wrong.
|
|
163
|
+
|
|
164
|
+
The blocks are independent of each other, so make sure `secret_key` (or `secret_key_path`) returns a key that
|
|
165
|
+
matches the algorithm returned by `signing_method` for the same options.
|
|
166
|
+
|
|
167
|
+
Note that the key options are only resolved when they are actually used: `secret_key_path` is read for
|
|
168
|
+
`RS*` and `ES*` algorithms only, and both `secret_key` and `secret_key_path` are skipped entirely when
|
|
169
|
+
`use_application_secret` is enabled. When a path is configured for an asymmetric algorithm it takes
|
|
170
|
+
precedence, and the `secret_key` block is not evaluated at all.
|
|
171
|
+
|
|
172
|
+
Whoever verifies these tokens now has more than one key to choose from, so tell them which one was used:
|
|
173
|
+
`token_headers` receives the same options hash and is evaluated per token as well, which lets you emit a
|
|
174
|
+
matching `kid` header.
|
|
175
|
+
|
|
176
|
+
```ruby
|
|
177
|
+
Doorkeeper::JWT.configure do
|
|
178
|
+
token_headers do |opts|
|
|
179
|
+
{ kid: opts[:scopes].exists?('admin') ? 'rsa-2026' : 'hmac-2026' }
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
See the `token_headers` entry in the configuration above for deriving the `kid` of an `RS*` key with
|
|
185
|
+
`JWT::JWK` instead of labelling it by hand.
|
|
186
|
+
|
|
106
187
|
## Development
|
|
107
188
|
|
|
108
189
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt
|
data/doorkeeper-jwt.gemspec
CHANGED
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
|
13
13
|
|
|
14
14
|
spec.summary = "JWT token generator for Doorkeeper"
|
|
15
15
|
spec.description = "JWT token generator extension for Doorkeeper"
|
|
16
|
-
spec.homepage = "https://github.com/
|
|
16
|
+
spec.homepage = "https://github.com/doorkeeper-gem/doorkeeper-jwt"
|
|
17
17
|
spec.license = "MIT"
|
|
18
18
|
|
|
19
19
|
spec.bindir = "exe"
|
|
@@ -30,6 +30,8 @@ Gem::Specification.new do |spec|
|
|
|
30
30
|
"funding_uri" => "https://opencollective.com/doorkeeper-gem",
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
spec.required_ruby_version = ">= 3.2"
|
|
34
|
+
|
|
33
35
|
# Loaded at require time by lib/doorkeeper/jwt/config.rb. The options DSL it
|
|
34
36
|
# relies on only resolves against our own builder since Doorkeeper 5.4.
|
|
35
37
|
spec.add_dependency "doorkeeper", ">= 5.4"
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "doorkeeper/config/option"
|
|
4
|
+
require "doorkeeper/jwt/errors"
|
|
4
5
|
|
|
5
6
|
module Doorkeeper
|
|
6
7
|
module JWT
|
|
7
|
-
class MissingConfiguration <
|
|
8
|
+
class MissingConfiguration < Error
|
|
8
9
|
def initialize
|
|
9
10
|
super("Configuration for doorkeeper-jwt missing.")
|
|
10
11
|
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Doorkeeper
|
|
4
|
+
module JWT
|
|
5
|
+
# Base class for every error raised by doorkeeper-jwt.
|
|
6
|
+
class Error < StandardError; end
|
|
7
|
+
|
|
8
|
+
# Raised when a signing key is configured but `signing_method` is not, so
|
|
9
|
+
# the only token that could be issued would be an unsigned (alg: none) one.
|
|
10
|
+
class SigningMethodMissing < Error; end
|
|
11
|
+
end
|
|
12
|
+
end
|
data/lib/doorkeeper/jwt.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "doorkeeper/jwt/version"
|
|
4
|
+
require "doorkeeper/jwt/errors"
|
|
4
5
|
require "doorkeeper/jwt/config"
|
|
5
6
|
require "jwt"
|
|
6
7
|
|
|
@@ -8,14 +9,22 @@ module Doorkeeper
|
|
|
8
9
|
module JWT
|
|
9
10
|
class << self
|
|
10
11
|
def generate(opts = {})
|
|
12
|
+
algorithm = signing_method(opts)
|
|
13
|
+
|
|
11
14
|
::JWT.encode(
|
|
12
15
|
token_payload(opts),
|
|
13
|
-
secret_key(opts),
|
|
14
|
-
|
|
16
|
+
secret_key(opts, algorithm),
|
|
17
|
+
algorithm,
|
|
15
18
|
token_headers(opts)
|
|
16
19
|
)
|
|
17
20
|
end
|
|
18
21
|
|
|
22
|
+
def signing_key_configured?
|
|
23
|
+
use_application_secret? ||
|
|
24
|
+
!Doorkeeper::JWT.configuration.secret_key.nil? ||
|
|
25
|
+
!Doorkeeper::JWT.configuration.secret_key_path.nil?
|
|
26
|
+
end
|
|
27
|
+
|
|
19
28
|
private
|
|
20
29
|
|
|
21
30
|
def token_payload(opts = {})
|
|
@@ -26,27 +35,61 @@ module Doorkeeper
|
|
|
26
35
|
Doorkeeper::JWT.configuration.token_headers.call(opts)
|
|
27
36
|
end
|
|
28
37
|
|
|
29
|
-
def secret_key(opts)
|
|
30
|
-
opts = { application: {} }.merge(opts)
|
|
31
|
-
|
|
38
|
+
def secret_key(opts, algorithm)
|
|
32
39
|
return application_secret(opts) if use_application_secret?
|
|
33
|
-
return secret_key_file unless secret_key_file.nil?
|
|
34
|
-
return rsa_key if rsa_signing?
|
|
35
|
-
return ecdsa_key if ecdsa_signing?
|
|
36
40
|
|
|
37
|
-
|
|
41
|
+
case algorithm
|
|
42
|
+
when /RS\d{3}/ then OpenSSL::PKey::RSA.new(asymmetric_key(opts))
|
|
43
|
+
when /ES\d{3}/ then OpenSSL::PKey::EC.new(asymmetric_key(opts))
|
|
44
|
+
else configured_secret_key(opts)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# A configured key file wins over `secret_key`, which is only resolved
|
|
49
|
+
# when no path is configured for this token.
|
|
50
|
+
def asymmetric_key(opts)
|
|
51
|
+
secret_key_file(opts) || configured_secret_key(opts)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def configured_secret_key(opts)
|
|
55
|
+
resolve_option(Doorkeeper::JWT.configuration.secret_key, opts)
|
|
38
56
|
end
|
|
39
57
|
|
|
40
|
-
def secret_key_file
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return ecdsa_key_file if ecdsa_signing?
|
|
58
|
+
def secret_key_file(opts)
|
|
59
|
+
path = resolve_option(Doorkeeper::JWT.configuration.secret_key_path, opts)
|
|
60
|
+
File.read(path) if path
|
|
44
61
|
end
|
|
45
62
|
|
|
46
|
-
def signing_method
|
|
47
|
-
|
|
63
|
+
def signing_method(opts)
|
|
64
|
+
method = resolve_option(Doorkeeper::JWT.configuration.signing_method, opts)
|
|
65
|
+
return method.to_s.upcase unless method.nil?
|
|
66
|
+
|
|
67
|
+
raise_missing_signing_method if signing_key_configured?
|
|
48
68
|
|
|
49
|
-
|
|
69
|
+
warn_unsigned_token
|
|
70
|
+
"none"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def raise_missing_signing_method
|
|
74
|
+
raise(
|
|
75
|
+
SigningMethodMissing,
|
|
76
|
+
"JWT `signing_method` is not configured, but a signing key is." \
|
|
77
|
+
" Refusing to issue an unsigned (alg: none) token. Set" \
|
|
78
|
+
" `signing_method` explicitly, e.g. `signing_method :hs512`."
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def warn_unsigned_token
|
|
83
|
+
Kernel.warn(
|
|
84
|
+
"[DOORKEEPER-JWT]: No `signing_method` configured; issuing UNSIGNED" \
|
|
85
|
+
" tokens (alg: none). This will become an error in a future release."
|
|
86
|
+
)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Options can be configured either with a static value or with a block
|
|
90
|
+
# that receives the token generation options and returns the value.
|
|
91
|
+
def resolve_option(value, opts)
|
|
92
|
+
value.respond_to?(:call) ? value.call(opts) : value
|
|
50
93
|
end
|
|
51
94
|
|
|
52
95
|
def use_application_secret?
|
|
@@ -54,6 +97,8 @@ module Doorkeeper
|
|
|
54
97
|
end
|
|
55
98
|
|
|
56
99
|
def application_secret(opts)
|
|
100
|
+
opts = { application: {} }.merge(opts)
|
|
101
|
+
|
|
57
102
|
if opts[:application].nil?
|
|
58
103
|
raise(
|
|
59
104
|
"JWT `use_application_secret` is enabled, but application is nil." \
|
|
@@ -82,34 +127,6 @@ module Doorkeeper
|
|
|
82
127
|
|
|
83
128
|
secret
|
|
84
129
|
end
|
|
85
|
-
|
|
86
|
-
def rsa_signing?
|
|
87
|
-
/RS\d{3}/ =~ signing_method
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def ecdsa_signing?
|
|
91
|
-
/ES\d{3}/ =~ signing_method
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def rsa_key
|
|
95
|
-
OpenSSL::PKey::RSA.new(Doorkeeper::JWT.configuration.secret_key)
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def ecdsa_key
|
|
99
|
-
OpenSSL::PKey::EC.new(Doorkeeper::JWT.configuration.secret_key)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def rsa_key_file
|
|
103
|
-
secret_key_file_open { |f| OpenSSL::PKey::RSA.new(f) }
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def ecdsa_key_file
|
|
107
|
-
secret_key_file_open { |f| OpenSSL::PKey::EC.new(f) }
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def secret_key_file_open(&block)
|
|
111
|
-
File.open(Doorkeeper::JWT.configuration.secret_key_path, &block)
|
|
112
|
-
end
|
|
113
130
|
end
|
|
114
131
|
end
|
|
115
132
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: doorkeeper-jwt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chris Warren
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: exe
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2026-
|
|
12
|
+
date: 2026-09-16 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: doorkeeper
|
|
@@ -117,8 +117,9 @@ files:
|
|
|
117
117
|
- doorkeeper-jwt.gemspec
|
|
118
118
|
- lib/doorkeeper/jwt.rb
|
|
119
119
|
- lib/doorkeeper/jwt/config.rb
|
|
120
|
+
- lib/doorkeeper/jwt/errors.rb
|
|
120
121
|
- lib/doorkeeper/jwt/version.rb
|
|
121
|
-
homepage: https://github.com/
|
|
122
|
+
homepage: https://github.com/doorkeeper-gem/doorkeeper-jwt
|
|
122
123
|
licenses:
|
|
123
124
|
- MIT
|
|
124
125
|
metadata:
|
|
@@ -135,7 +136,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
135
136
|
requirements:
|
|
136
137
|
- - ">="
|
|
137
138
|
- !ruby/object:Gem::Version
|
|
138
|
-
version: '
|
|
139
|
+
version: '3.2'
|
|
139
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
141
|
requirements:
|
|
141
142
|
- - ">="
|