devise-jwt 0.6.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +1 -2
- data/.github/FUNDING.yml +1 -0
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +21 -0
- data/.github/workflows/lint.yml +17 -0
- data/.rubocop.yml +40 -1
- data/CHANGELOG.md +29 -1
- data/Dockerfile +7 -9
- data/LICENSE.txt +1 -1
- data/README.md +141 -66
- data/bin/console +5 -4
- data/devise-jwt.gemspec +9 -7
- data/docker-compose.yml +7 -2
- data/issue_template.md +1 -0
- data/lib/devise/jwt/defaults_generator.rb +0 -4
- data/lib/devise/jwt/mapping_inspector.rb +0 -2
- data/lib/devise/jwt/railtie.rb +9 -0
- data/lib/devise/jwt/revocation_strategies/{whitelist.rb → allowlist.rb} +8 -9
- data/lib/devise/jwt/revocation_strategies/{blacklist.rb → denylist.rb} +1 -1
- data/lib/devise/jwt/revocation_strategies.rb +2 -2
- data/lib/devise/jwt/test_helpers.rb +2 -7
- data/lib/devise/jwt/version.rb +1 -1
- data/lib/devise/jwt.rb +31 -19
- metadata +45 -32
- data/.overcommit.yml +0 -56
- data/.overcommit_gems.rb +0 -15
- data/.reek +0 -0
- data/.travis.yml +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2edd445c57c9d9cd2ed101bc9fd9e2678a4ef8dee9b671d168e5083a08edff2b
|
4
|
+
data.tar.gz: 2e8c86be9239ac50fe91589ddacc9110c8df84887d7f2e72a5477afa325fc961
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d9658efde24910caf33abbfdc4ad050900a7904db121612c57023d74db89f5912cadc01c9b1cb69709ece57485b99743ce8c2c3b9f9a86fb6347ce54f270489
|
7
|
+
data.tar.gz: d01552367f5d62ce7b454434d97f840f90c2bafe284c3d5c5ae83bb4fdf541056c895613b7dfb1556d2858fb8a521d824e87f7c08a96aec439ef4aa6d7f6c0c6
|
data/.codeclimate.yml
CHANGED
data/.github/FUNDING.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
github: waiting-for-dev
|
@@ -0,0 +1,21 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
strategy:
|
9
|
+
matrix:
|
10
|
+
ruby-version: ['3.0', '3.1', '3.2', ruby-head]
|
11
|
+
|
12
|
+
steps:
|
13
|
+
- uses: actions/checkout@v3
|
14
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
15
|
+
uses: ruby/setup-ruby@v1
|
16
|
+
with:
|
17
|
+
ruby-version: ${{ matrix.ruby-version }}
|
18
|
+
bundler-cache: true # 'bundle install' and cache
|
19
|
+
- name: Run specs
|
20
|
+
run: |
|
21
|
+
bundle exec rspec
|
@@ -0,0 +1,17 @@
|
|
1
|
+
name: Lint
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
lint:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
steps:
|
9
|
+
- uses: actions/checkout@v3
|
10
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
11
|
+
uses: ruby/setup-ruby@v1
|
12
|
+
with:
|
13
|
+
ruby-version: 2.7
|
14
|
+
bundler-cache: true # 'bundle install' and cache
|
15
|
+
- name: Run specs
|
16
|
+
run: |
|
17
|
+
bundle exec rubocop
|
data/.rubocop.yml
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
require: rubocop-rspec
|
2
2
|
AllCops:
|
3
|
-
TargetRubyVersion:
|
3
|
+
TargetRubyVersion: 3.0
|
4
|
+
Exclude:
|
5
|
+
- Gemfile
|
6
|
+
- devise-jwt.gemspec
|
7
|
+
- spec/fixtures/rails_app/**/*
|
8
|
+
- vendor/**/*
|
4
9
|
RSpec/NestedGroups:
|
5
10
|
Max: 3
|
6
11
|
RSpec/MessageExpectation:
|
@@ -14,3 +19,37 @@ Metrics/BlockLength:
|
|
14
19
|
- "spec/**/*.rb"
|
15
20
|
Style/SafeNavigation:
|
16
21
|
Enabled: false
|
22
|
+
Layout/EmptyLinesAroundAttributeAccessor:
|
23
|
+
Enabled: true
|
24
|
+
Layout/SpaceAroundMethodCallOperator:
|
25
|
+
Enabled: true
|
26
|
+
Lint/DeprecatedOpenSSLConstant:
|
27
|
+
Enabled: true
|
28
|
+
Lint/MixedRegexpCaptureTypes:
|
29
|
+
Enabled: true
|
30
|
+
Lint/RaiseException:
|
31
|
+
Enabled: true
|
32
|
+
Lint/StructNewOverride:
|
33
|
+
Enabled: true
|
34
|
+
Style/AccessorGrouping:
|
35
|
+
Enabled: true
|
36
|
+
Style/BisectedAttrAccessor:
|
37
|
+
Enabled: true
|
38
|
+
Style/ExponentialNotation:
|
39
|
+
Enabled: true
|
40
|
+
Style/HashEachMethods:
|
41
|
+
Enabled: true
|
42
|
+
Style/HashTransformKeys:
|
43
|
+
Enabled: true
|
44
|
+
Style/HashTransformValues:
|
45
|
+
Enabled: true
|
46
|
+
Style/RedundantAssignment:
|
47
|
+
Enabled: true
|
48
|
+
Style/RedundantFetchBlock:
|
49
|
+
Enabled: true
|
50
|
+
Style/RedundantRegexpCharacterClass:
|
51
|
+
Enabled: true
|
52
|
+
Style/RedundantRegexpEscape:
|
53
|
+
Enabled: true
|
54
|
+
Style/SlicingWithRange:
|
55
|
+
Enabled: true
|
data/CHANGELOG.md
CHANGED
@@ -4,7 +4,35 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
6
6
|
|
7
|
-
## [0.
|
7
|
+
## [0.11.0] - 2023-05-10
|
8
|
+
### Added
|
9
|
+
- Add support for rotation_secret
|
10
|
+
|
11
|
+
## [0.10.0] - 2022-09-16
|
12
|
+
### Added
|
13
|
+
- Enable support for asymmetric algorithms
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
- FIX: "No verification key available" on token decode
|
17
|
+
|
18
|
+
## [0.9.0] - 2021-09-21
|
19
|
+
### Fixed
|
20
|
+
- Fix compatibility with dry-configurable 0.13
|
21
|
+
|
22
|
+
## [0.8.1] - 2021-02-14
|
23
|
+
### Fixed
|
24
|
+
- Fix behaviour on code reload
|
25
|
+
- Support ruby 3.0 and deprecate ruby 2.5
|
26
|
+
|
27
|
+
## [0.8.0] - 2020-07-06
|
28
|
+
### Fixed
|
29
|
+
- Fix compatibility with last version of dry-configurable
|
30
|
+
|
31
|
+
## [0.7.0] - 2020-06-03
|
32
|
+
### Fixed
|
33
|
+
- Replace whitelist/blacklist terminology with allowlist/denylist
|
34
|
+
|
35
|
+
## [0.6.0] - 2019-08-01
|
8
36
|
### Fixed
|
9
37
|
- Update warden-jwt_auth dependency to v0.4.0 so that now it is possible to configure algorithm.
|
10
38
|
|
data/Dockerfile
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
FROM ruby:
|
2
|
-
ENV
|
3
|
-
|
4
|
-
|
5
|
-
RUN
|
6
|
-
|
7
|
-
|
8
|
-
COPY $LIB_DIR/version.rb $APP_HOME/$LIB_DIR
|
9
|
-
RUN bundle install
|
1
|
+
FROM ruby:3.0.0
|
2
|
+
ENV APP_USER devise_jwt_user
|
3
|
+
RUN apt-get update -qq && \
|
4
|
+
apt-get install -y build-essential sqlite3 libsqlite3-dev
|
5
|
+
RUN useradd -ms /bin/bash $APP_USER
|
6
|
+
USER $APP_USER
|
7
|
+
WORKDIR /home/$APP_USER/app
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -5,28 +5,50 @@
|
|
5
5
|
[![Code Climate](https://codeclimate.com/github/waiting-for-dev/devise-jwt/badges/gpa.svg)](https://codeclimate.com/github/waiting-for-dev/devise-jwt)
|
6
6
|
[![Test Coverage](https://codeclimate.com/github/waiting-for-dev/devise-jwt/badges/coverage.svg)](https://codeclimate.com/github/waiting-for-dev/devise-jwt/coverage)
|
7
7
|
|
8
|
-
`devise-jwt` is a [
|
8
|
+
`devise-jwt` is a [Devise](https://github.com/plataformatec/devise) extension which uses [JWT](https://jwt.io/) tokens for user authentication. It follows [secure by default](https://en.wikipedia.org/wiki/Secure_by_default) principle.
|
9
9
|
|
10
|
-
This gem is just a replacement for cookies when these can't be used. As
|
11
|
-
cookies, a
|
10
|
+
This gem is just a replacement for cookies when these can't be used. As with
|
11
|
+
cookies, a `devise-jwt` token will mandatorily have an expiration
|
12
12
|
time. If you need that your users never sign out, you will be better off with a
|
13
13
|
solution using refresh tokens, like some implementation of OAuth2.
|
14
14
|
|
15
15
|
You can read about which security concerns this library takes into account and about JWT generic secure usage in the following series of posts:
|
16
16
|
|
17
|
-
- [Stand Up for JWT Revocation](http://waiting-for-dev.github.io/blog/2017/01/23/stand_up_for_jwt_revocation
|
18
|
-
- [JWT Revocation Strategies](http://waiting-for-dev.github.io/blog/2017/01/24/jwt_revocation_strategies
|
19
|
-
- [JWT Secure Usage](http://waiting-for-dev.github.io/blog/2017/01/25/jwt_secure_usage
|
20
|
-
- [A secure JWT authentication implementation for Rack and Rails](http://waiting-for-dev.github.io/blog/2017/01/26/a_secure_jwt_authentication_implementation_for_rack_and_rails
|
17
|
+
- [Stand Up for JWT Revocation](http://waiting-for-dev.github.io/blog/2017/01/23/stand_up_for_jwt_revocation)
|
18
|
+
- [JWT Revocation Strategies](http://waiting-for-dev.github.io/blog/2017/01/24/jwt_revocation_strategies)
|
19
|
+
- [JWT Secure Usage](http://waiting-for-dev.github.io/blog/2017/01/25/jwt_secure_usage)
|
20
|
+
- [A secure JWT authentication implementation for Rack and Rails](http://waiting-for-dev.github.io/blog/2017/01/26/a_secure_jwt_authentication_implementation_for_rack_and_rails)
|
21
21
|
|
22
|
-
`devise-jwt` is just a thin layer on top of [`warden-jwt_auth`](https://github.com/waiting-for-dev/warden-jwt_auth) that configures it to be used out of the box with
|
22
|
+
`devise-jwt` is just a thin layer on top of [`warden-jwt_auth`](https://github.com/waiting-for-dev/warden-jwt_auth) that configures it to be used out of the box with Devise and Rails.
|
23
|
+
|
24
|
+
## Upgrade notes
|
25
|
+
|
26
|
+
### v0.7.0
|
27
|
+
|
28
|
+
Since version v0.7.0 `Blacklist` revocation strategy has been renamed to `Denylist` while `Whitelist` has been renamed to `Allowlist`.
|
29
|
+
|
30
|
+
For `Denylist`, you only need to update the `include` line you're using in your revocation strategy model:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
# include Devise::JWT::RevocationStrategies::Blacklist # before
|
34
|
+
include Devise::JWT::RevocationStrategies::Denylist
|
35
|
+
```
|
36
|
+
|
37
|
+
For `Allowlist`, you need to update the `include` line you're using in your user model:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
# include Devise::JWT::RevocationStrategies::Whitelist # before
|
41
|
+
include Devise::JWT::RevocationStrategies::Allowlist
|
42
|
+
```
|
43
|
+
|
44
|
+
You also have to rename your `WhitelistedJwt` model to `AllowlistedJwt`, rename `model/whitelisted_jwt.rb` to `model/allowlisted_jwt.rb` and change the underlying database table to `allowlisted_jwts` (or configure the model to keep using the old name).
|
23
45
|
|
24
46
|
## Installation
|
25
47
|
|
26
48
|
Add this line to your application's Gemfile:
|
27
49
|
|
28
50
|
```ruby
|
29
|
-
gem 'devise-jwt'
|
51
|
+
gem 'devise-jwt'
|
30
52
|
```
|
31
53
|
|
32
54
|
And then execute:
|
@@ -39,11 +61,11 @@ Or install it yourself as:
|
|
39
61
|
|
40
62
|
## Usage
|
41
63
|
|
42
|
-
First you need to configure
|
64
|
+
First, you need to configure Devise to work in an API application. You can follow the instructions in this project wiki page [Configuring Devise for APIs](https://github.com/waiting-for-dev/devise-jwt/wiki/Configuring-devise-for-APIs) (you are more than welcome to improve them).
|
43
65
|
|
44
66
|
### Secret key configuration
|
45
67
|
|
46
|
-
|
68
|
+
You have to configure the secret key that will be used to sign generated tokens. You can do it in the Devise initializer:
|
47
69
|
|
48
70
|
```ruby
|
49
71
|
Devise.setup do |config|
|
@@ -54,33 +76,81 @@ Devise.setup do |config|
|
|
54
76
|
end
|
55
77
|
```
|
56
78
|
|
57
|
-
|
79
|
+
If you are using Encrypted Credentials (Rails 5.2+), you can store the secret key in `config/credentials.yml.enc`.
|
80
|
+
|
81
|
+
Open your credentials editor using `bin/rails credentials:edit` and add `devise_jwt_secret_key`.
|
82
|
+
|
83
|
+
> **Note** you may need to set `$EDITOR` depending on your specific environment.
|
84
|
+
|
85
|
+
```yml
|
86
|
+
|
87
|
+
# Other secrets...
|
88
|
+
|
89
|
+
# Used as the base secret for Devise JWT
|
90
|
+
devise_jwt_secret_key: abc...xyz
|
91
|
+
```
|
92
|
+
|
93
|
+
Add the following to the Devise initializer.
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
Devise.setup do |config|
|
97
|
+
# ...
|
98
|
+
config.jwt do |jwt|
|
99
|
+
jwt.secret = Rails.application.credentials.devise_jwt_secret_key!
|
100
|
+
end
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
> **Important:** You are encouraged to use a secret different than your application `secret_key_base`. It is quite possible that some other component of your system is already using it. If several components share the same secret key, chances that a vulnerability in one of them has a wider impact increase. In rails, generating new secrets is as easy as `bundle exec rake secret`. Also, never share your secrets pushing it to a remote repository, you are better off using an environment variable like in the example.
|
105
|
+
|
106
|
+
Currently, HS256 algorithm is the one in use. You may configure a matching secret and algorithm name to use a different one (see [ruby-jwt](https://github.com/jwt/ruby-jwt#algorithms-and-usage) to see which are supported):
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
Devise.setup do |config|
|
110
|
+
# ...
|
111
|
+
config.jwt do |jwt|
|
112
|
+
jwt.secret = OpenSSL::PKey::RSA.new(Rails.application.credentials.devise_jwt_secret_key!)
|
113
|
+
jwt.algorithm = Rails.application.credentials.devise_jwt_algorithm!
|
114
|
+
end
|
115
|
+
end
|
116
|
+
```
|
58
117
|
|
59
|
-
|
118
|
+
If the algorithm is asymmetric (e.g. RS256) which necessitates a different decoding secret, configure the `decoding_secret` setting as well:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
Devise.setup do |config|
|
122
|
+
# ...
|
123
|
+
config.jwt do |jwt|
|
124
|
+
jwt.secret = OpenSSL::PKey::RSA.new(Rails.application.credentials.devise_jwt_private_key!)
|
125
|
+
jwt.decoding_secret = OpenSSL::PKey::RSA.new(Rails.application.credentials.devise_jwt_public_key!)
|
126
|
+
jwt.algorithm = 'RS256' # or some other asymmetric algorithm
|
127
|
+
end
|
128
|
+
end
|
129
|
+
```
|
60
130
|
|
61
131
|
### Model configuration
|
62
132
|
|
63
133
|
You have to tell which user models you want to be able to authenticate with JWT tokens. For them, the authentication process will be like this:
|
64
134
|
|
65
|
-
- A user authenticates through
|
135
|
+
- A user authenticates through Devise create session request (for example, using the standard `:database_authenticatable` module).
|
66
136
|
- If the authentication succeeds, a JWT token is dispatched to the client in the `Authorization` response header, with format `Bearer #{token}` (tokens are also dispatched on a successful sign up).
|
67
137
|
- The client can use this token to authenticate following requests for the same user, providing it in the `Authorization` request header, also with format `Bearer #{token}`
|
68
|
-
- When the client visits
|
138
|
+
- When the client visits Devise destroy session request, the token is revoked.
|
69
139
|
|
70
140
|
See [request_formats](#request_formats) configuration option if you are using paths with a format segment (like `.json`) in order to use it properly.
|
71
141
|
|
72
|
-
As you see, unlike other JWT authentication libraries, it is expected that tokens will be revoked by the server. I wrote about [why I think JWT revocation is needed and useful](http://waiting-for-dev.github.io/blog/2017/01/23/stand_up_for_jwt_revocation
|
142
|
+
As you see, unlike other JWT authentication libraries, it is expected that tokens will be revoked by the server. I wrote about [why I think JWT revocation is needed and useful](http://waiting-for-dev.github.io/blog/2017/01/23/stand_up_for_jwt_revocation).
|
73
143
|
|
74
144
|
An example configuration:
|
75
145
|
|
76
146
|
```ruby
|
77
147
|
class User < ApplicationRecord
|
78
148
|
devise :database_authenticatable,
|
79
|
-
:jwt_authenticatable, jwt_revocation_strategy:
|
149
|
+
:jwt_authenticatable, jwt_revocation_strategy: Denylist
|
80
150
|
end
|
81
151
|
```
|
82
152
|
|
83
|
-
If you need to add something to the JWT payload, you can do it defining a `jwt_payload` method in the user model. It must return a `Hash`. For instance:
|
153
|
+
If you need to add something to the JWT payload, you can do it by defining a `jwt_payload` method in the user model. It must return a `Hash`. For instance:
|
84
154
|
|
85
155
|
```ruby
|
86
156
|
def jwt_payload
|
@@ -114,11 +184,11 @@ end
|
|
114
184
|
#### Session storage caveat
|
115
185
|
|
116
186
|
If you are working with a Rails application that has session storage enabled
|
117
|
-
and a default
|
187
|
+
and a default Devise setup, chances are the same origin requests will be
|
118
188
|
authenticated from the session regardless of a token being present in the
|
119
189
|
headers or not.
|
120
190
|
|
121
|
-
This is so because of the following default
|
191
|
+
This is so because of the following default Devise workflow:
|
122
192
|
|
123
193
|
- When a user signs in with `:database_authenticatable` strategy, the user is
|
124
194
|
stored in the session unless one of the following conditions is met:
|
@@ -128,13 +198,13 @@ This is so because of the following default devise workflow:
|
|
128
198
|
protection](http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html)
|
129
199
|
handles an unverified request (but this is usually deactivated for API
|
130
200
|
requests).
|
131
|
-
- Warden (the engine below
|
132
|
-
in the session without
|
201
|
+
- Warden (the engine below Devise), authenticates any request that the user has
|
202
|
+
in the session without requiring a strategy (`:jwt_authenticatable`
|
133
203
|
in our case).
|
134
204
|
|
135
|
-
So, if you want to avoid this caveat you have
|
205
|
+
So, if you want to avoid this caveat you have three options:
|
136
206
|
|
137
|
-
- Disable the session. If you are developing an API, probably
|
207
|
+
- Disable the session. If you are developing an API, you probably don't need
|
138
208
|
it. In order to disable it, change `config/initializers/session_store.rb` to:
|
139
209
|
```ruby
|
140
210
|
Rails.application.config.session_store :disabled
|
@@ -146,18 +216,27 @@ So, if you want to avoid this caveat you have two options:
|
|
146
216
|
```ruby
|
147
217
|
config.skip_session_storage = [:http_auth, :params_auth]
|
148
218
|
```
|
219
|
+
- If you are using Devise for another model (e.g. `AdminUser`) and doesn't want
|
220
|
+
to disable session storage for Devise entirely, you can disable it on a
|
221
|
+
per-model basis:
|
222
|
+
```ruby
|
223
|
+
class User < ApplicationRecord
|
224
|
+
devise :database_authenticatable #, your other enabled modules...
|
225
|
+
self.skip_session_storage = [:http_auth, :params_auth]
|
226
|
+
end
|
227
|
+
```
|
149
228
|
|
150
229
|
### Revocation strategies
|
151
230
|
|
152
|
-
`devise-jwt` comes with three revocation strategies out of the box. Some of them are implementations of what is discussed in the blog post [JWT Revocation Strategies](http://waiting-for-dev.github.io/blog/2017/01/24/jwt_revocation_strategies
|
231
|
+
`devise-jwt` comes with three revocation strategies out of the box. Some of them are implementations of what is discussed in the blog post [JWT Revocation Strategies](http://waiting-for-dev.github.io/blog/2017/01/24/jwt_revocation_strategies), where I also talk about their pros and cons.
|
153
232
|
|
154
233
|
#### JTIMatcher
|
155
234
|
|
156
|
-
Here, the model class acts
|
235
|
+
Here, the model class acts as the revocation strategy. It needs a new string column named `jti` to be added to the user. `jti` stands for JWT ID, and it is a standard claim meant to uniquely identify a token.
|
157
236
|
|
158
237
|
It works like the following:
|
159
238
|
|
160
|
-
-
|
239
|
+
- When a token is dispatched for a user, the `jti` claim is taken from the `jti` column in the model (which has been initialized when the record has been created).
|
161
240
|
- At every authenticated action, the incoming token `jti` claim is matched against the `jti` column for that user. The authentication only succeeds if they are the same.
|
162
241
|
- When the user requests to sign out its `jti` column changes, so that provided token won't be valid anymore.
|
163
242
|
|
@@ -196,29 +275,29 @@ def jwt_payload
|
|
196
275
|
end
|
197
276
|
```
|
198
277
|
|
199
|
-
####
|
278
|
+
#### Denylist
|
200
279
|
|
201
|
-
In this strategy, a database table is used as a
|
280
|
+
In this strategy, a database table is used as a list of revoked JWT tokens. The `jti` claim, which uniquely identifies a token, is persisted. The `exp` claim is also stored to allow the clean-up of stale tokens.
|
202
281
|
|
203
|
-
In order to use it, you need to create the
|
282
|
+
In order to use it, you need to create the denylist table in a migration:
|
204
283
|
|
205
284
|
```ruby
|
206
285
|
def change
|
207
|
-
create_table :
|
286
|
+
create_table :jwt_denylist do |t|
|
208
287
|
t.string :jti, null: false
|
209
288
|
t.datetime :exp, null: false
|
210
289
|
end
|
211
|
-
add_index :
|
290
|
+
add_index :jwt_denylist, :jti
|
212
291
|
end
|
213
292
|
```
|
214
293
|
For performance reasons, it is better if the `jti` column is an index.
|
215
294
|
|
216
|
-
Note: if you used the
|
295
|
+
Note: if you used the denylist strategy before version 0.4.0 you may not have the field *exp.* If not, run the following migration:
|
217
296
|
|
218
297
|
```ruby
|
219
|
-
class
|
298
|
+
class AddExpirationTimeToJWTDenylist < ActiveRecord::Migration
|
220
299
|
def change
|
221
|
-
add_column :
|
300
|
+
add_column :jwt_denylist, :exp, :datetime, null: false
|
222
301
|
end
|
223
302
|
end
|
224
303
|
|
@@ -227,10 +306,10 @@ end
|
|
227
306
|
Then, you need to create the corresponding model and include the strategy:
|
228
307
|
|
229
308
|
```ruby
|
230
|
-
class
|
231
|
-
include Devise::JWT::RevocationStrategies::
|
309
|
+
class JwtDenylist < ApplicationRecord
|
310
|
+
include Devise::JWT::RevocationStrategies::Denylist
|
232
311
|
|
233
|
-
self.table_name = '
|
312
|
+
self.table_name = 'jwt_denylist'
|
234
313
|
end
|
235
314
|
```
|
236
315
|
|
@@ -239,15 +318,15 @@ Last, configure the user model to use it:
|
|
239
318
|
```ruby
|
240
319
|
class User < ApplicationRecord
|
241
320
|
devise :database_authenticatable,
|
242
|
-
:jwt_authenticatable, jwt_revocation_strategy:
|
321
|
+
:jwt_authenticatable, jwt_revocation_strategy: JwtDenylist
|
243
322
|
end
|
244
323
|
```
|
245
324
|
|
246
|
-
####
|
325
|
+
#### Allowlist
|
247
326
|
|
248
|
-
Here, the model itself acts
|
327
|
+
Here, the model itself also acts as a revocation strategy, but it needs to have
|
249
328
|
a one-to-many association with another table which stores the tokens (in fact
|
250
|
-
their `jti` claim, which uniquely identifies them)
|
329
|
+
their `jti` claim, which uniquely identifies them) that are valid for each user record.
|
251
330
|
|
252
331
|
The workflow is as the following:
|
253
332
|
|
@@ -265,12 +344,12 @@ devices for the same user.
|
|
265
344
|
|
266
345
|
The `exp` claim is also stored to allow the clean-up of staled tokens.
|
267
346
|
|
268
|
-
In order to use it, you have to create
|
269
|
-
The association table must be called `
|
347
|
+
In order to use it, you have to create the associated table and model.
|
348
|
+
The association table must be called `allowlisted_jwts`:
|
270
349
|
|
271
350
|
```ruby
|
272
351
|
def change
|
273
|
-
create_table :
|
352
|
+
create_table :allowlisted_jwts do |t|
|
274
353
|
t.string :jti, null: false
|
275
354
|
t.string :aud
|
276
355
|
# If you want to leverage the `aud` claim, add to it a `NOT NULL` constraint:
|
@@ -279,15 +358,15 @@ def change
|
|
279
358
|
t.references :your_user_table, foreign_key: { on_delete: :cascade }, null: false
|
280
359
|
end
|
281
360
|
|
282
|
-
add_index :
|
361
|
+
add_index :allowlisted_jwts, :jti, unique: true
|
283
362
|
end
|
284
363
|
```
|
285
|
-
Important: You are encouraged to set a unique index in the jti column. This way we can be sure at the database level that there aren't two valid tokens with same jti at the same time.
|
364
|
+
Important: You are encouraged to set a unique index in the `jti` column. This way we can be sure at the database level that there aren't two valid tokens with the same `jti` at the same time. Defining `foreign_key: { on_delete: :cascade }, null: false` on `t.references :your_user_table` helps to keep referential integrity of your database.
|
286
365
|
|
287
366
|
And then, the model:
|
288
367
|
|
289
368
|
```ruby
|
290
|
-
class
|
369
|
+
class AllowlistedJwt < ApplicationRecord
|
291
370
|
end
|
292
371
|
```
|
293
372
|
|
@@ -295,7 +374,7 @@ Finally, include the strategy in the model and configure it:
|
|
295
374
|
|
296
375
|
```ruby
|
297
376
|
class User < ApplicationRecord
|
298
|
-
include Devise::JWT::RevocationStrategies::
|
377
|
+
include Devise::JWT::RevocationStrategies::Allowlist
|
299
378
|
|
300
379
|
devise :database_authenticatable,
|
301
380
|
:jwt_authenticatable, jwt_revocation_strategy: self
|
@@ -324,7 +403,7 @@ end
|
|
324
403
|
|
325
404
|
#### Custom strategies
|
326
405
|
|
327
|
-
You can also implement your own strategies. They just need to implement two methods: `jwt_revoked?` and `revoke_jwt`, both of them
|
406
|
+
You can also implement your own strategies. They just need to implement two methods: `jwt_revoked?` and `revoke_jwt`, both of them accept the JWT payload and the user record as parameters, in this order.
|
328
407
|
|
329
408
|
For instance:
|
330
409
|
|
@@ -348,10 +427,10 @@ end
|
|
348
427
|
### Testing
|
349
428
|
|
350
429
|
Models configured with `:jwt_authenticatable` usually won't be retrieved from
|
351
|
-
the session. For this reason, `sign_in`
|
430
|
+
the session. For this reason, `sign_in` Devise testing helper methods won't
|
352
431
|
work as expected.
|
353
432
|
|
354
|
-
What you need to do
|
433
|
+
What you need to do to authenticate test environment requests is the
|
355
434
|
same that you will do in production: to provide a valid token in the
|
356
435
|
`Authorization` header (in the form of `Bearer #{token}`) at every request.
|
357
436
|
|
@@ -389,7 +468,7 @@ Usually you will wrap this in your own test helper.
|
|
389
468
|
|
390
469
|
### Configuration reference
|
391
470
|
|
392
|
-
This library can be configured calling `jwt` on
|
471
|
+
This library can be configured calling `jwt` on Devise config object:
|
393
472
|
|
394
473
|
```ruby
|
395
474
|
Devise.setup do |config|
|
@@ -400,17 +479,21 @@ end
|
|
400
479
|
```
|
401
480
|
#### secret
|
402
481
|
|
403
|
-
Secret key used to sign generated JWT tokens. You must set it.
|
482
|
+
Secret key is used to sign generated JWT tokens. You must set it.
|
483
|
+
|
484
|
+
#### rotation_secret
|
485
|
+
|
486
|
+
Allow rotating secrets. Set a new value to `secret` and copy the old secret to `rotation_secret`.
|
404
487
|
|
405
488
|
#### expiration_time
|
406
489
|
|
407
490
|
Number of seconds while a JWT is valid after its generation. After that, it won't be valid anymore, even if it hasn't been revoked.
|
408
491
|
|
409
|
-
Defaults to 3600 (1 hour).
|
492
|
+
Defaults to 3600 seconds (1 hour).
|
410
493
|
|
411
494
|
#### dispatch_requests
|
412
495
|
|
413
|
-
Besides the create session one, additional requests where JWT tokens should be dispatched.
|
496
|
+
Besides the create session one, there are additional requests where JWT tokens should be dispatched.
|
414
497
|
|
415
498
|
It must be a bidimensional array, each item being an array of two elements: the request method and a regular expression that must match the request path.
|
416
499
|
|
@@ -427,7 +510,7 @@ jwt.dispatch_requests = [
|
|
427
510
|
|
428
511
|
#### revocation_requests
|
429
512
|
|
430
|
-
Besides the destroy session one, additional requests where JWT tokens should be revoked.
|
513
|
+
Besides the destroy session one, there are additional requests where JWT tokens should be revoked.
|
431
514
|
|
432
515
|
It must be a bidimensional array, each item being an array of two elements: the request method and a regular expression that must match the request path.
|
433
516
|
|
@@ -446,7 +529,7 @@ jwt.revocation_requests = [
|
|
446
529
|
|
447
530
|
Request formats that must be processed (in order to dispatch or revoke tokens).
|
448
531
|
|
449
|
-
It must be a hash of
|
532
|
+
It must be a hash of Devise scopes as keys and an array of request formats as
|
450
533
|
values. When a scope is not present or if it has a nil item, requests without
|
451
534
|
format will be taken into account.
|
452
535
|
|
@@ -490,14 +573,6 @@ An then, for example:
|
|
490
573
|
|
491
574
|
`docker-compose exec app rspec`
|
492
575
|
|
493
|
-
This gem uses [overcommit](https://github.com/brigade/overcommit) to execute some code review engines. If you submit a pull request, it will be executed in the CI process. In order to set it up, you need to do:
|
494
|
-
|
495
|
-
```ruby
|
496
|
-
bundle install --gemfile=.overcommit_gems.rb
|
497
|
-
overcommit --sign
|
498
|
-
overcommit --run # To test if it works
|
499
|
-
```
|
500
|
-
|
501
576
|
## Contributing
|
502
577
|
|
503
578
|
Bug reports and pull requests are welcome on GitHub at https://github.com/waiting-for-dev/devise-jwt. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
data/bin/console
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
-
require
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'devise/jwt'
|
5
6
|
|
6
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
8
|
# with your gem easier. You can also use a different console, if you like.
|
8
9
|
|
9
10
|
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require
|
11
|
+
# require 'pry'
|
11
12
|
# Pry.start
|
12
13
|
|
13
|
-
require
|
14
|
+
require 'irb'
|
14
15
|
IRB.start
|
data/devise-jwt.gemspec
CHANGED
@@ -22,17 +22,19 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
24
|
spec.add_dependency 'devise', '~> 4.0'
|
25
|
-
spec.add_dependency 'warden-jwt_auth', '~> 0.
|
25
|
+
spec.add_dependency 'warden-jwt_auth', '~> 0.8'
|
26
26
|
|
27
27
|
spec.add_development_dependency "bundler", "> 1"
|
28
|
-
spec.add_development_dependency "rake", "~>
|
29
|
-
spec.add_development_dependency "rspec"
|
30
|
-
spec.add_development_dependency "pry-byebug", "~> 3.7"
|
28
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
29
|
+
spec.add_development_dependency "rspec"
|
31
30
|
# Needed to test the rails fixture application
|
32
|
-
spec.add_development_dependency 'rails', '~>
|
31
|
+
spec.add_development_dependency 'rails', '~> 6.0'
|
33
32
|
spec.add_development_dependency 'sqlite3', '~> 1.3'
|
34
|
-
spec.add_development_dependency 'rspec-rails', '~>
|
33
|
+
spec.add_development_dependency 'rspec-rails', '~> 4.0'
|
34
|
+
# Cops
|
35
|
+
spec.add_development_dependency 'rubocop', '~> 0.87'
|
36
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 1.42'
|
35
37
|
# Test reporting
|
36
|
-
spec.add_development_dependency 'simplecov', '
|
38
|
+
spec.add_development_dependency 'simplecov', '0.17'
|
37
39
|
spec.add_development_dependency 'codeclimate-test-reporter', '~> 1.0'
|
38
40
|
end
|
data/docker-compose.yml
CHANGED
data/issue_template.md
CHANGED
@@ -18,6 +18,7 @@ Provide following information. Please, format pasted output as code. Feel free t
|
|
18
18
|
|
19
19
|
- Version of `devise-jwt` in use
|
20
20
|
- Version of `rails` in use
|
21
|
+
- Version of `warden-jwt_auth` in use
|
21
22
|
- Output of `Devise::JWT.config`
|
22
23
|
- Output of `Warden::JWTAuth.config`
|
23
24
|
- Output of `Devise.mappings`
|
@@ -42,14 +42,12 @@ module Devise
|
|
42
42
|
add_revocation_requests(inspector)
|
43
43
|
end
|
44
44
|
|
45
|
-
# :reek:FeatureEnvy
|
46
45
|
def add_mapping(inspector)
|
47
46
|
scope = inspector.scope
|
48
47
|
model = inspector.model
|
49
48
|
defaults[:mappings][scope] = model.name
|
50
49
|
end
|
51
50
|
|
52
|
-
# :reek:FeatureEnvy
|
53
51
|
def add_revocation_strategy(inspector)
|
54
52
|
scope = inspector.scope
|
55
53
|
strategy = inspector.model.jwt_revocation_strategy
|
@@ -91,7 +89,6 @@ module Devise
|
|
91
89
|
requests(inspector, :registration)
|
92
90
|
end
|
93
91
|
|
94
|
-
# :reek:FeatureEnvy
|
95
92
|
def requests(inspector, name)
|
96
93
|
path = inspector.path(name)
|
97
94
|
methods = inspector.methods(name)
|
@@ -100,7 +97,6 @@ module Devise
|
|
100
97
|
end
|
101
98
|
end
|
102
99
|
|
103
|
-
# :reek:UtilityFunction
|
104
100
|
def requests_for_format(path, methods, format)
|
105
101
|
path_regexp = format ? /^#{path}.#{format}$/ : /^#{path}$/
|
106
102
|
methods.map do |method|
|
@@ -27,7 +27,6 @@ module Devise
|
|
27
27
|
mapping.to
|
28
28
|
end
|
29
29
|
|
30
|
-
# :reek:FeatureEnvy
|
31
30
|
def path(name)
|
32
31
|
prefix, scope, request = path_parts(name)
|
33
32
|
[prefix, scope, request].delete_if do |item|
|
@@ -35,7 +34,6 @@ module Devise
|
|
35
34
|
end.join('/').prepend('/').gsub('//', '/')
|
36
35
|
end
|
37
36
|
|
38
|
-
# :reek:ControlParameter
|
39
37
|
def methods(name)
|
40
38
|
method = case name
|
41
39
|
when :sign_in then 'POST'
|
data/lib/devise/jwt/railtie.rb
CHANGED
@@ -21,6 +21,15 @@ module Devise
|
|
21
21
|
config.revocation_strategies = defaults[:revocation_strategies]
|
22
22
|
end
|
23
23
|
end
|
24
|
+
|
25
|
+
ActiveSupport::Reloader.to_prepare do
|
26
|
+
Warden::JWTAuth.configure do |config|
|
27
|
+
defaults = DefaultsGenerator.call
|
28
|
+
|
29
|
+
config.mappings = defaults[:mappings]
|
30
|
+
config.revocation_strategies = defaults[:revocation_strategies]
|
31
|
+
end
|
32
|
+
end
|
24
33
|
end
|
25
34
|
end
|
26
35
|
end
|
@@ -7,40 +7,39 @@ module Devise
|
|
7
7
|
module RevocationStrategies
|
8
8
|
# This strategy must be included in the user model.
|
9
9
|
#
|
10
|
-
# The
|
10
|
+
# The JwtAllowlist table must include `jti`, `aud`, `exp` and `user_id`
|
11
11
|
# columns
|
12
12
|
#
|
13
13
|
# In order to tell whether a token is revoked, it just tries to find the
|
14
|
-
# `jti` and `aud` values from the token on the `
|
14
|
+
# `jti` and `aud` values from the token on the `allowlisted_jwts`
|
15
15
|
# table for the respective user.
|
16
16
|
#
|
17
17
|
# If the values don't exist means the token was revoked.
|
18
18
|
# On revocation, it deletes the matching record from the
|
19
|
-
# `
|
19
|
+
# `allowlisted_jwts` table.
|
20
20
|
#
|
21
21
|
# On sign in, it creates a new record with the `jti` and `aud` values.
|
22
|
-
module
|
22
|
+
module Allowlist
|
23
23
|
extend ActiveSupport::Concern
|
24
24
|
|
25
25
|
included do
|
26
|
-
has_many :
|
26
|
+
has_many :allowlisted_jwts, dependent: :destroy
|
27
27
|
|
28
28
|
# @see Warden::JWTAuth::Interfaces::RevocationStrategy#jwt_revoked?
|
29
29
|
def self.jwt_revoked?(payload, user)
|
30
|
-
!user.
|
30
|
+
!user.allowlisted_jwts.exists?(payload.slice('jti', 'aud'))
|
31
31
|
end
|
32
32
|
|
33
33
|
# @see Warden::JWTAuth::Interfaces::RevocationStrategy#revoke_jwt
|
34
34
|
def self.revoke_jwt(payload, user)
|
35
|
-
jwt = user.
|
35
|
+
jwt = user.allowlisted_jwts.find_by(payload.slice('jti', 'aud'))
|
36
36
|
jwt.destroy! if jwt
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
40
|
# Warden::JWTAuth::Interfaces::User#on_jwt_dispatch
|
41
|
-
# :reek:FeatureEnvy
|
42
41
|
def on_jwt_dispatch(_token, payload)
|
43
|
-
|
42
|
+
allowlisted_jwts.create!(
|
44
43
|
jti: payload['jti'],
|
45
44
|
aud: payload['aud'],
|
46
45
|
exp: Time.at(payload['exp'].to_i)
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'devise/jwt/revocation_strategies/jti_matcher'
|
4
|
-
require 'devise/jwt/revocation_strategies/
|
5
|
-
require 'devise/jwt/revocation_strategies/
|
4
|
+
require 'devise/jwt/revocation_strategies/denylist'
|
5
|
+
require 'devise/jwt/revocation_strategies/allowlist'
|
6
6
|
require 'devise/jwt/revocation_strategies/null'
|
7
7
|
|
8
8
|
module Devise
|
@@ -9,7 +9,7 @@ module Devise
|
|
9
9
|
#
|
10
10
|
# Side effects could happen if you have implemented
|
11
11
|
# `on_jwt_dispatch` method on the user model (as it happens in
|
12
|
-
# the
|
12
|
+
# the allowlist revocation strategy).
|
13
13
|
#
|
14
14
|
# Be aware that a fresh copy of `headers` is returned with the new
|
15
15
|
# key/value pair added, instead of modifying given argument.
|
@@ -20,18 +20,13 @@ module Devise
|
|
20
20
|
# autodetected.
|
21
21
|
# @param aud [String] The aud claim. If `nil` it will be autodetected from
|
22
22
|
# the header name configured in `Devise::JWT.config.aud_header`.
|
23
|
-
#
|
24
|
-
# :reek:LongParameterList
|
25
|
-
# :reek:ManualDispatch
|
26
23
|
def self.auth_headers(headers, user, scope: nil, aud: nil)
|
27
24
|
scope ||= Devise::Mapping.find_scope!(user)
|
28
25
|
aud ||= headers[Warden::JWTAuth.config.aud_header]
|
29
26
|
token, payload = Warden::JWTAuth::UserEncoder.new.call(
|
30
27
|
user, scope, aud
|
31
28
|
)
|
32
|
-
if user.respond_to?(:on_jwt_dispatch)
|
33
|
-
user.on_jwt_dispatch(token, payload)
|
34
|
-
end
|
29
|
+
user.on_jwt_dispatch(token, payload) if user.respond_to?(:on_jwt_dispatch)
|
35
30
|
Warden::JWTAuth::HeaderParser.to_headers(headers, token)
|
36
31
|
end
|
37
32
|
end
|
data/lib/devise/jwt/version.rb
CHANGED
data/lib/devise/jwt.rb
CHANGED
@@ -26,25 +26,41 @@ module Devise
|
|
26
26
|
module JWT
|
27
27
|
extend Dry::Configurable
|
28
28
|
|
29
|
-
setting
|
30
|
-
|
29
|
+
def self.forward_to_warden(setting, value)
|
30
|
+
default = Warden::JWTAuth.config.send(setting)
|
31
|
+
Warden::JWTAuth.config.send("#{setting}=", value || default)
|
32
|
+
Warden::JWTAuth.config.send(setting)
|
31
33
|
end
|
32
34
|
|
33
|
-
setting(:
|
34
|
-
|
35
|
-
|
35
|
+
setting(:secret,
|
36
|
+
default: Warden::JWTAuth.config.secret,
|
37
|
+
constructor: ->(value) { forward_to_warden(:secret, value) })
|
36
38
|
|
37
|
-
setting(:
|
38
|
-
|
39
|
-
|
39
|
+
setting(:rotation_secret,
|
40
|
+
default: Warden::JWTAuth.config.rotation_secret,
|
41
|
+
constructor: ->(value) { forward_to_warden(:rotation_secret, value) })
|
40
42
|
|
41
|
-
setting(:
|
42
|
-
|
43
|
-
end
|
43
|
+
setting(:decoding_secret,
|
44
|
+
constructor: ->(value) { forward_to_warden(:decoding_secret, value) })
|
44
45
|
|
45
|
-
setting(:
|
46
|
-
|
47
|
-
|
46
|
+
setting(:algorithm,
|
47
|
+
constructor: ->(value) { forward_to_warden(:algorithm, value) })
|
48
|
+
|
49
|
+
setting(:expiration_time,
|
50
|
+
default: Warden::JWTAuth.config.expiration_time,
|
51
|
+
constructor: ->(value) { forward_to_warden(:expiration_time, value) })
|
52
|
+
|
53
|
+
setting(:dispatch_requests,
|
54
|
+
default: Warden::JWTAuth.config.dispatch_requests,
|
55
|
+
constructor: ->(value) { forward_to_warden(:dispatch_requests, value) })
|
56
|
+
|
57
|
+
setting(:revocation_requests,
|
58
|
+
default: Warden::JWTAuth.config.revocation_requests,
|
59
|
+
constructor: ->(value) { forward_to_warden(:revocation_requests, value) })
|
60
|
+
|
61
|
+
setting(:aud_header,
|
62
|
+
default: Warden::JWTAuth.config.aud_header,
|
63
|
+
constructor: ->(value) { forward_to_warden(:aud_header, value) })
|
48
64
|
|
49
65
|
# A hash of warden scopes as keys and an array of request formats that will
|
50
66
|
# be processed as values. When a scope is not present or if it has a nil
|
@@ -59,10 +75,6 @@ module Devise
|
|
59
75
|
# user: [:json],
|
60
76
|
# admin_user: [nil, :xml]
|
61
77
|
# }
|
62
|
-
setting :request_formats, {}
|
63
|
-
|
64
|
-
def self.forward_to_warden(setting, value)
|
65
|
-
Warden::JWTAuth.config.send("#{setting}=", value)
|
66
|
-
end
|
78
|
+
setting :request_formats, default: {}
|
67
79
|
end
|
68
80
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise-jwt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marc Busqué
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: devise
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0.
|
33
|
+
version: '0.8'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0.
|
40
|
+
version: '0.8'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,98 +58,112 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '13.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '13.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rails
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
87
|
- - "~>"
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
89
|
+
version: '6.0'
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
94
|
- - "~>"
|
81
95
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
96
|
+
version: '6.0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
98
|
+
name: sqlite3
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
101
|
- - "~>"
|
88
102
|
- !ruby/object:Gem::Version
|
89
|
-
version: '3
|
103
|
+
version: '1.3'
|
90
104
|
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
108
|
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version: '3
|
110
|
+
version: '1.3'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
|
-
name: rails
|
112
|
+
name: rspec-rails
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
115
|
- - "~>"
|
102
116
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
117
|
+
version: '4.0'
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
122
|
- - "~>"
|
109
123
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
124
|
+
version: '4.0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
126
|
+
name: rubocop
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
129
|
- - "~>"
|
116
130
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
131
|
+
version: '0.87'
|
118
132
|
type: :development
|
119
133
|
prerelease: false
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
136
|
- - "~>"
|
123
137
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
138
|
+
version: '0.87'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
|
-
name: rspec
|
140
|
+
name: rubocop-rspec
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
143
|
- - "~>"
|
130
144
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
145
|
+
version: '1.42'
|
132
146
|
type: :development
|
133
147
|
prerelease: false
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
150
|
- - "~>"
|
137
151
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
152
|
+
version: '1.42'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
name: simplecov
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
142
156
|
requirements:
|
143
|
-
- -
|
157
|
+
- - '='
|
144
158
|
- !ruby/object:Gem::Version
|
145
|
-
version: '0.
|
159
|
+
version: '0.17'
|
146
160
|
type: :development
|
147
161
|
prerelease: false
|
148
162
|
version_requirements: !ruby/object:Gem::Requirement
|
149
163
|
requirements:
|
150
|
-
- -
|
164
|
+
- - '='
|
151
165
|
- !ruby/object:Gem::Version
|
152
|
-
version: '0.
|
166
|
+
version: '0.17'
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
168
|
name: codeclimate-test-reporter
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
@@ -172,13 +186,13 @@ extensions: []
|
|
172
186
|
extra_rdoc_files: []
|
173
187
|
files:
|
174
188
|
- ".codeclimate.yml"
|
189
|
+
- ".github/FUNDING.yml"
|
190
|
+
- ".github/dependabot.yml"
|
191
|
+
- ".github/workflows/ci.yml"
|
192
|
+
- ".github/workflows/lint.yml"
|
175
193
|
- ".gitignore"
|
176
|
-
- ".overcommit.yml"
|
177
|
-
- ".overcommit_gems.rb"
|
178
|
-
- ".reek"
|
179
194
|
- ".rspec"
|
180
195
|
- ".rubocop.yml"
|
181
|
-
- ".travis.yml"
|
182
196
|
- CHANGELOG.md
|
183
197
|
- CODE_OF_CONDUCT.md
|
184
198
|
- Dockerfile
|
@@ -198,10 +212,10 @@ files:
|
|
198
212
|
- lib/devise/jwt/models/jwt_authenticatable.rb
|
199
213
|
- lib/devise/jwt/railtie.rb
|
200
214
|
- lib/devise/jwt/revocation_strategies.rb
|
201
|
-
- lib/devise/jwt/revocation_strategies/
|
215
|
+
- lib/devise/jwt/revocation_strategies/allowlist.rb
|
216
|
+
- lib/devise/jwt/revocation_strategies/denylist.rb
|
202
217
|
- lib/devise/jwt/revocation_strategies/jti_matcher.rb
|
203
218
|
- lib/devise/jwt/revocation_strategies/null.rb
|
204
|
-
- lib/devise/jwt/revocation_strategies/whitelist.rb
|
205
219
|
- lib/devise/jwt/test_helpers.rb
|
206
220
|
- lib/devise/jwt/version.rb
|
207
221
|
homepage: https://github.com/waiting-for-dev/devise-jwt
|
@@ -223,8 +237,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
223
237
|
- !ruby/object:Gem::Version
|
224
238
|
version: '0'
|
225
239
|
requirements: []
|
226
|
-
|
227
|
-
rubygems_version: 2.7.8
|
240
|
+
rubygems_version: 3.3.7
|
228
241
|
signing_key:
|
229
242
|
specification_version: 4
|
230
243
|
summary: JWT authentication for devise
|
data/.overcommit.yml
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Select version of overcommit and the other tools from Gemfile
|
3
|
-
#
|
4
|
-
gemfile: .overcommit_gems.rb
|
5
|
-
|
6
|
-
#
|
7
|
-
# Hooks that are run against every commit message after a user has written it.
|
8
|
-
#
|
9
|
-
CommitMsg:
|
10
|
-
ALL:
|
11
|
-
required: true
|
12
|
-
exclude: &default_excludes
|
13
|
-
- Gemfile
|
14
|
-
- devise-jwt.gemspec
|
15
|
-
- spec/fixtures/rails_app/**/*
|
16
|
-
- README.md
|
17
|
-
- CHANGELOG.md
|
18
|
-
|
19
|
-
HardTabs:
|
20
|
-
enabled: true
|
21
|
-
|
22
|
-
SingleLineSubject:
|
23
|
-
enabled: true
|
24
|
-
|
25
|
-
#
|
26
|
-
# Hooks that are run after `git commit` is executed, before the commit message
|
27
|
-
# editor is displayed.
|
28
|
-
#
|
29
|
-
PreCommit:
|
30
|
-
ALL:
|
31
|
-
required: true
|
32
|
-
exclude: *default_excludes
|
33
|
-
|
34
|
-
BundleAudit:
|
35
|
-
enabled: true
|
36
|
-
|
37
|
-
BundleCheck:
|
38
|
-
enabled: true
|
39
|
-
|
40
|
-
LocalPathsInGemfile:
|
41
|
-
enabled: true
|
42
|
-
|
43
|
-
ExecutePermissions:
|
44
|
-
enabled: true
|
45
|
-
exclude:
|
46
|
-
- *default_excludes
|
47
|
-
- bin/*
|
48
|
-
|
49
|
-
Reek:
|
50
|
-
enabled: true
|
51
|
-
|
52
|
-
RuboCop:
|
53
|
-
enabled: true
|
54
|
-
|
55
|
-
TrailingWhitespace:
|
56
|
-
enabled: true
|
data/.overcommit_gems.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
source 'https://rubygems.org'
|
4
|
-
|
5
|
-
gem 'overcommit', '~> 0.36'
|
6
|
-
|
7
|
-
# Patch-level verification for Bundled apps
|
8
|
-
gem 'bundler-audit', '~> 0.5'
|
9
|
-
|
10
|
-
# Ruby code smell reporter
|
11
|
-
gem 'reek', '~> 4.5'
|
12
|
-
|
13
|
-
# Ruby code style checking
|
14
|
-
gem 'rubocop', '~> 0.47'
|
15
|
-
gem 'rubocop-rspec', '~> 1.10'
|
data/.reek
DELETED
File without changes
|
data/.travis.yml
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
sudo: false
|
2
|
-
language: ruby
|
3
|
-
rvm:
|
4
|
-
- 2.3
|
5
|
-
- 2.4
|
6
|
-
- 2.5
|
7
|
-
before_install:
|
8
|
-
- gem update --system --no-doc
|
9
|
-
- bundle install --gemfile=.overcommit_gems.rb
|
10
|
-
before_script:
|
11
|
-
- git config --global user.email 'travis@travis.ci'
|
12
|
-
- git config --global user.name 'Travis CI'
|
13
|
-
script:
|
14
|
-
- bundle exec rspec
|
15
|
-
- bundle exec codeclimate-test-reporter
|
16
|
-
- overcommit --sign
|
17
|
-
- overcommit --run
|
18
|
-
addons:
|
19
|
-
code_climate:
|
20
|
-
repo_token:
|
21
|
-
secure: OWVschEUE+pVEQFR9dgtCUVmf2GJF3e7RTvX9M3CS7fhLyWqDlHdkCxmxCGJQDBVXR59ReCni2sbbRgkfqekkggLEG3gvHl2uof9+PVVRXTbDDDydwDGHLvcT8ZVJOHVgqgX899j6eBSsqdtSB7rMEdMOYBYDw35/yd844LkaW+sOWUbx0SJSo0V0QtJe3DC7vTAo/EEGTQs7WRGcXa6Pg9RlWiK7ThVoEbXQ4GDdjS5mWsQer4QcdnOfiuBL8mC3XAX+wJyBIqAVetAmhFKtwH+pKYMqRbcI/iBSaHslGowLr+tQW/tLO9XZsz95C6037XUse6BUJ5U9mYsgcnebslVJnuQ4dyXTXwQ2e1Fzy4iYr9Iz2Yhr3EjchXOvXh0D2BDPLCZMF98W/hsPZ4hPq/FhfjdfJXHcuqU6k7Ozr6UTwMmuNMvR7af2hXGaralTPOH8SVh/RtxpWsAocNA4n1b7dhdpMLKDNZ7GxdunDo5zJ03HUH4d0SDexnx3xSpfR/q+FJDHNxfD7KVAsgQYnrNjde/DnYszV2E3EAUVWF71ZaNQIvDyS1gyBjjvkSGRGL5tY7z+sdaRfE68toidgl2eR08vt/eYo3DIIzwPvI5N/BTv/Xm8vQ+jfwxCF6Ezr1TJTZW4auoMBAVqrr4HoO6T7VHTOeUD0Bukp7KBfQ=
|