sorcery-jwt 0.2.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +10 -3
- data/.gitignore +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +25 -0
- data/Gemfile.lock +220 -5
- data/README.md +86 -36
- data/gemfiles/sorcery_0.16.5.gemfile +4 -0
- data/gemfiles/sorcery_0.16.5.gemfile.lock +278 -0
- data/gemfiles/sorcery_0.17.0.gemfile +4 -0
- data/gemfiles/sorcery_0.17.0.gemfile.lock +278 -0
- data/gemfiles/sorcery_0.18.0.gemfile +4 -0
- data/gemfiles/sorcery_0.18.0.gemfile.lock +307 -0
- data/lib/sorcery/controller/submodules/jwt.rb +7 -0
- data/lib/sorcery/jwt/version.rb +1 -1
- data/lib/sorcery/model/submodules/jwt.rb +23 -2
- data/sorcery-jwt.gemspec +6 -1
- metadata +56 -6
- data/PLAN.md +0 -94
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: ..
|
|
3
|
+
specs:
|
|
4
|
+
sorcery-jwt (0.2.1)
|
|
5
|
+
jwt (>= 1.0, < 3.0)
|
|
6
|
+
sorcery (>= 0.16.5, < 0.19)
|
|
7
|
+
|
|
8
|
+
GEM
|
|
9
|
+
remote: https://rubygems.org/
|
|
10
|
+
specs:
|
|
11
|
+
action_text-trix (2.1.19)
|
|
12
|
+
railties
|
|
13
|
+
actioncable (8.1.3.1)
|
|
14
|
+
actionpack (= 8.1.3.1)
|
|
15
|
+
activesupport (= 8.1.3.1)
|
|
16
|
+
nio4r (~> 2.0)
|
|
17
|
+
websocket-driver (>= 0.6.1)
|
|
18
|
+
zeitwerk (~> 2.6)
|
|
19
|
+
actionmailbox (8.1.3.1)
|
|
20
|
+
actionpack (= 8.1.3.1)
|
|
21
|
+
activejob (= 8.1.3.1)
|
|
22
|
+
activerecord (= 8.1.3.1)
|
|
23
|
+
activestorage (= 8.1.3.1)
|
|
24
|
+
activesupport (= 8.1.3.1)
|
|
25
|
+
mail (>= 2.8.0)
|
|
26
|
+
actionmailer (8.1.3.1)
|
|
27
|
+
actionpack (= 8.1.3.1)
|
|
28
|
+
actionview (= 8.1.3.1)
|
|
29
|
+
activejob (= 8.1.3.1)
|
|
30
|
+
activesupport (= 8.1.3.1)
|
|
31
|
+
mail (>= 2.8.0)
|
|
32
|
+
rails-dom-testing (~> 2.2)
|
|
33
|
+
actionpack (8.1.3.1)
|
|
34
|
+
actionview (= 8.1.3.1)
|
|
35
|
+
activesupport (= 8.1.3.1)
|
|
36
|
+
nokogiri (>= 1.8.5)
|
|
37
|
+
rack (>= 2.2.4)
|
|
38
|
+
rack-session (>= 1.0.1)
|
|
39
|
+
rack-test (>= 0.6.3)
|
|
40
|
+
rails-dom-testing (~> 2.2)
|
|
41
|
+
rails-html-sanitizer (~> 1.6)
|
|
42
|
+
useragent (~> 0.16)
|
|
43
|
+
actiontext (8.1.3.1)
|
|
44
|
+
action_text-trix (~> 2.1.15)
|
|
45
|
+
actionpack (= 8.1.3.1)
|
|
46
|
+
activerecord (= 8.1.3.1)
|
|
47
|
+
activestorage (= 8.1.3.1)
|
|
48
|
+
activesupport (= 8.1.3.1)
|
|
49
|
+
globalid (>= 0.6.0)
|
|
50
|
+
nokogiri (>= 1.8.5)
|
|
51
|
+
actionview (8.1.3.1)
|
|
52
|
+
activesupport (= 8.1.3.1)
|
|
53
|
+
builder (~> 3.1)
|
|
54
|
+
erubi (~> 1.11)
|
|
55
|
+
rails-dom-testing (~> 2.2)
|
|
56
|
+
rails-html-sanitizer (~> 1.6)
|
|
57
|
+
activejob (8.1.3.1)
|
|
58
|
+
activesupport (= 8.1.3.1)
|
|
59
|
+
globalid (>= 0.3.6)
|
|
60
|
+
activemodel (8.1.3.1)
|
|
61
|
+
activesupport (= 8.1.3.1)
|
|
62
|
+
activerecord (8.1.3.1)
|
|
63
|
+
activemodel (= 8.1.3.1)
|
|
64
|
+
activesupport (= 8.1.3.1)
|
|
65
|
+
timeout (>= 0.4.0)
|
|
66
|
+
activestorage (8.1.3.1)
|
|
67
|
+
actionpack (= 8.1.3.1)
|
|
68
|
+
activejob (= 8.1.3.1)
|
|
69
|
+
activerecord (= 8.1.3.1)
|
|
70
|
+
activesupport (= 8.1.3.1)
|
|
71
|
+
marcel (~> 1.0)
|
|
72
|
+
activesupport (8.1.3.1)
|
|
73
|
+
base64
|
|
74
|
+
bigdecimal
|
|
75
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
76
|
+
connection_pool (>= 2.2.5)
|
|
77
|
+
drb
|
|
78
|
+
i18n (>= 1.6, < 2)
|
|
79
|
+
json
|
|
80
|
+
logger (>= 1.4.2)
|
|
81
|
+
minitest (>= 5.1)
|
|
82
|
+
securerandom (>= 0.3)
|
|
83
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
|
84
|
+
uri (>= 0.13.1)
|
|
85
|
+
anonymous_loader (0.1.3)
|
|
86
|
+
version_gem (~> 1.1, >= 1.1.14)
|
|
87
|
+
auth-sanitizer (0.2.3)
|
|
88
|
+
version_gem (~> 1.1, >= 1.1.14)
|
|
89
|
+
base64 (0.3.0)
|
|
90
|
+
bcrypt (3.1.22)
|
|
91
|
+
bigdecimal (4.1.2)
|
|
92
|
+
builder (3.3.0)
|
|
93
|
+
concurrent-ruby (1.3.8)
|
|
94
|
+
connection_pool (3.0.2)
|
|
95
|
+
crass (1.0.7)
|
|
96
|
+
date (3.5.1)
|
|
97
|
+
diff-lcs (1.6.2)
|
|
98
|
+
drb (2.2.3)
|
|
99
|
+
erb (6.0.7)
|
|
100
|
+
erubi (1.13.1)
|
|
101
|
+
faraday (2.14.3)
|
|
102
|
+
faraday-net_http (>= 2.0, < 3.5)
|
|
103
|
+
json
|
|
104
|
+
logger
|
|
105
|
+
faraday-net_http (3.4.4)
|
|
106
|
+
net-http (~> 0.5)
|
|
107
|
+
globalid (1.4.0)
|
|
108
|
+
activesupport (>= 6.1)
|
|
109
|
+
hashie (5.1.0)
|
|
110
|
+
logger
|
|
111
|
+
i18n (1.15.2)
|
|
112
|
+
concurrent-ruby (~> 1.0)
|
|
113
|
+
io-console (0.9.2)
|
|
114
|
+
irb (1.18.0)
|
|
115
|
+
pp (>= 0.6.0)
|
|
116
|
+
prism (>= 1.3.0)
|
|
117
|
+
rdoc (>= 4.0.0)
|
|
118
|
+
reline (>= 0.4.2)
|
|
119
|
+
json (2.21.2)
|
|
120
|
+
jwt (2.10.3)
|
|
121
|
+
base64
|
|
122
|
+
logger (1.7.0)
|
|
123
|
+
loofah (2.25.2)
|
|
124
|
+
crass (~> 1.0.2)
|
|
125
|
+
nokogiri (>= 1.12.0)
|
|
126
|
+
mail (2.9.1)
|
|
127
|
+
logger
|
|
128
|
+
mini_mime (>= 0.1.1)
|
|
129
|
+
net-imap
|
|
130
|
+
net-pop
|
|
131
|
+
net-smtp
|
|
132
|
+
marcel (1.2.1)
|
|
133
|
+
mini_mime (1.1.5)
|
|
134
|
+
minitest (6.0.6)
|
|
135
|
+
drb (~> 2.0)
|
|
136
|
+
prism (~> 1.5)
|
|
137
|
+
multi_xml (0.9.1)
|
|
138
|
+
bigdecimal (>= 3.1, < 5)
|
|
139
|
+
net-http (0.9.1)
|
|
140
|
+
uri (>= 0.11.1)
|
|
141
|
+
net-imap (0.6.6)
|
|
142
|
+
date
|
|
143
|
+
net-protocol
|
|
144
|
+
net-pop (0.1.2)
|
|
145
|
+
net-protocol
|
|
146
|
+
net-protocol (0.3.0)
|
|
147
|
+
timeout
|
|
148
|
+
net-smtp (0.5.1)
|
|
149
|
+
net-protocol
|
|
150
|
+
nio4r (2.7.5)
|
|
151
|
+
nokogiri (1.19.4-aarch64-linux-gnu)
|
|
152
|
+
racc (~> 1.4)
|
|
153
|
+
nokogiri (1.19.4-aarch64-linux-musl)
|
|
154
|
+
racc (~> 1.4)
|
|
155
|
+
nokogiri (1.19.4-arm-linux-gnu)
|
|
156
|
+
racc (~> 1.4)
|
|
157
|
+
nokogiri (1.19.4-arm-linux-musl)
|
|
158
|
+
racc (~> 1.4)
|
|
159
|
+
nokogiri (1.19.4-arm64-darwin)
|
|
160
|
+
racc (~> 1.4)
|
|
161
|
+
nokogiri (1.19.4-x86_64-darwin)
|
|
162
|
+
racc (~> 1.4)
|
|
163
|
+
nokogiri (1.19.4-x86_64-linux-gnu)
|
|
164
|
+
racc (~> 1.4)
|
|
165
|
+
nokogiri (1.19.4-x86_64-linux-musl)
|
|
166
|
+
racc (~> 1.4)
|
|
167
|
+
oauth (1.1.8)
|
|
168
|
+
anonymous_loader (~> 0.1, >= 0.1.3)
|
|
169
|
+
auth-sanitizer (~> 0.2, >= 0.2.3)
|
|
170
|
+
base64 (~> 0.1)
|
|
171
|
+
oauth-tty (~> 1.0, >= 1.0.13)
|
|
172
|
+
snaky_hash (~> 2.0, >= 2.0.7)
|
|
173
|
+
version_gem (~> 1.1, >= 1.1.14)
|
|
174
|
+
oauth-tty (1.0.13)
|
|
175
|
+
anonymous_loader (~> 0.1, >= 0.1.3)
|
|
176
|
+
auth-sanitizer (~> 0.2, >= 0.2.3)
|
|
177
|
+
version_gem (~> 1.1, >= 1.1.14)
|
|
178
|
+
oauth2 (2.0.25)
|
|
179
|
+
anonymous_loader (~> 0.1, >= 0.1.3)
|
|
180
|
+
auth-sanitizer (~> 0.2, >= 0.2.3)
|
|
181
|
+
faraday (>= 0.17.3, < 4.0)
|
|
182
|
+
jwt (>= 1.0, < 4.0)
|
|
183
|
+
logger (~> 1.2)
|
|
184
|
+
multi_xml (~> 0.5)
|
|
185
|
+
rack (>= 1.2, < 4)
|
|
186
|
+
snaky_hash (~> 2.0, >= 2.0.7)
|
|
187
|
+
version_gem (~> 1.1, >= 1.1.14)
|
|
188
|
+
pp (0.6.4)
|
|
189
|
+
prettyprint
|
|
190
|
+
prettyprint (0.2.0)
|
|
191
|
+
prism (1.9.0)
|
|
192
|
+
racc (1.8.1)
|
|
193
|
+
rack (3.2.7)
|
|
194
|
+
rack-session (2.1.2)
|
|
195
|
+
base64 (>= 0.1.0)
|
|
196
|
+
rack (>= 3.0.0)
|
|
197
|
+
rack-test (2.2.0)
|
|
198
|
+
rack (>= 1.3)
|
|
199
|
+
rackup (2.3.1)
|
|
200
|
+
rack (>= 3)
|
|
201
|
+
rails (8.1.3.1)
|
|
202
|
+
actioncable (= 8.1.3.1)
|
|
203
|
+
actionmailbox (= 8.1.3.1)
|
|
204
|
+
actionmailer (= 8.1.3.1)
|
|
205
|
+
actionpack (= 8.1.3.1)
|
|
206
|
+
actiontext (= 8.1.3.1)
|
|
207
|
+
actionview (= 8.1.3.1)
|
|
208
|
+
activejob (= 8.1.3.1)
|
|
209
|
+
activemodel (= 8.1.3.1)
|
|
210
|
+
activerecord (= 8.1.3.1)
|
|
211
|
+
activestorage (= 8.1.3.1)
|
|
212
|
+
activesupport (= 8.1.3.1)
|
|
213
|
+
bundler (>= 1.15.0)
|
|
214
|
+
railties (= 8.1.3.1)
|
|
215
|
+
rails-dom-testing (2.3.0)
|
|
216
|
+
activesupport (>= 5.0.0)
|
|
217
|
+
minitest
|
|
218
|
+
nokogiri (>= 1.6)
|
|
219
|
+
rails-html-sanitizer (1.7.1)
|
|
220
|
+
loofah (~> 2.25, >= 2.25.2)
|
|
221
|
+
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
|
222
|
+
railties (8.1.3.1)
|
|
223
|
+
actionpack (= 8.1.3.1)
|
|
224
|
+
activesupport (= 8.1.3.1)
|
|
225
|
+
irb (~> 1.13)
|
|
226
|
+
rackup (>= 1.0.0)
|
|
227
|
+
rake (>= 12.2)
|
|
228
|
+
thor (~> 1.0, >= 1.2.2)
|
|
229
|
+
tsort (>= 0.2)
|
|
230
|
+
zeitwerk (~> 2.6)
|
|
231
|
+
rake (13.4.2)
|
|
232
|
+
rbs (4.2.0)
|
|
233
|
+
logger
|
|
234
|
+
prism (>= 1.6.0)
|
|
235
|
+
tsort
|
|
236
|
+
rdoc (8.0.0)
|
|
237
|
+
erb
|
|
238
|
+
prism (>= 1.6.0)
|
|
239
|
+
rbs (>= 4.0.0)
|
|
240
|
+
tsort
|
|
241
|
+
reline (0.7.0)
|
|
242
|
+
io-console (~> 0.5)
|
|
243
|
+
rspec (3.13.2)
|
|
244
|
+
rspec-core (~> 3.13.0)
|
|
245
|
+
rspec-expectations (~> 3.13.0)
|
|
246
|
+
rspec-mocks (~> 3.13.0)
|
|
247
|
+
rspec-core (3.13.6)
|
|
248
|
+
rspec-support (~> 3.13.0)
|
|
249
|
+
rspec-expectations (3.13.5)
|
|
250
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
251
|
+
rspec-support (~> 3.13.0)
|
|
252
|
+
rspec-mocks (3.13.8)
|
|
253
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
254
|
+
rspec-support (~> 3.13.0)
|
|
255
|
+
rspec-support (3.13.7)
|
|
256
|
+
securerandom (0.4.1)
|
|
257
|
+
snaky_hash (2.0.7)
|
|
258
|
+
hashie (>= 0.1.0, < 6)
|
|
259
|
+
version_gem (~> 1.1, >= 1.1.14)
|
|
260
|
+
sorcery (0.18.0)
|
|
261
|
+
bcrypt (~> 3.1)
|
|
262
|
+
oauth (>= 0.6)
|
|
263
|
+
oauth2 (~> 2.0)
|
|
264
|
+
railties (>= 7.1)
|
|
265
|
+
sqlite3 (2.9.6-aarch64-linux-gnu)
|
|
266
|
+
sqlite3 (2.9.6-aarch64-linux-musl)
|
|
267
|
+
sqlite3 (2.9.6-arm-linux-gnu)
|
|
268
|
+
sqlite3 (2.9.6-arm-linux-musl)
|
|
269
|
+
sqlite3 (2.9.6-arm64-darwin)
|
|
270
|
+
sqlite3 (2.9.6-x86_64-darwin)
|
|
271
|
+
sqlite3 (2.9.6-x86_64-linux-gnu)
|
|
272
|
+
sqlite3 (2.9.6-x86_64-linux-musl)
|
|
273
|
+
thor (1.5.0)
|
|
274
|
+
timeout (0.6.1)
|
|
275
|
+
tsort (0.2.0)
|
|
276
|
+
tzinfo (2.0.6)
|
|
277
|
+
concurrent-ruby (~> 1.0)
|
|
278
|
+
uri (1.1.1)
|
|
279
|
+
useragent (0.16.11)
|
|
280
|
+
version_gem (1.1.15)
|
|
281
|
+
websocket-driver (0.8.2)
|
|
282
|
+
base64
|
|
283
|
+
websocket-extensions (>= 0.1.0)
|
|
284
|
+
websocket-extensions (0.1.5)
|
|
285
|
+
zeitwerk (2.8.3)
|
|
286
|
+
|
|
287
|
+
PLATFORMS
|
|
288
|
+
aarch64-linux-gnu
|
|
289
|
+
aarch64-linux-musl
|
|
290
|
+
arm-linux-gnu
|
|
291
|
+
arm-linux-musl
|
|
292
|
+
arm64-darwin
|
|
293
|
+
x86_64-darwin
|
|
294
|
+
x86_64-linux-gnu
|
|
295
|
+
x86_64-linux-musl
|
|
296
|
+
|
|
297
|
+
DEPENDENCIES
|
|
298
|
+
activerecord (~> 8.0)
|
|
299
|
+
rails (~> 8.0)
|
|
300
|
+
rake (~> 13.0)
|
|
301
|
+
rspec (~> 3.0)
|
|
302
|
+
sorcery (= 0.18.0)
|
|
303
|
+
sorcery-jwt!
|
|
304
|
+
sqlite3 (~> 2.0)
|
|
305
|
+
|
|
306
|
+
BUNDLED WITH
|
|
307
|
+
2.6.9
|
|
@@ -10,6 +10,9 @@ module Sorcery
|
|
|
10
10
|
module InstanceMethods
|
|
11
11
|
protected
|
|
12
12
|
|
|
13
|
+
# A sorcery login source: authenticates the request from the
|
|
14
|
+
# Authorization header when it carries a validly signed, unexpired
|
|
15
|
+
# JWT whose id and email claims match a user.
|
|
13
16
|
def login_from_jwt
|
|
14
17
|
claims = decoded_token.first.slice("id", "email")
|
|
15
18
|
return @current_user = nil if claims.empty?
|
|
@@ -21,6 +24,10 @@ module Sorcery
|
|
|
21
24
|
@current_user = nil
|
|
22
25
|
end
|
|
23
26
|
|
|
27
|
+
# Authenticates credentials via sorcery and, on success, issues a
|
|
28
|
+
# JWT for the user carrying its id and email claims.
|
|
29
|
+
#
|
|
30
|
+
# @return [String, nil] the JWT, or nil when credentials fail
|
|
24
31
|
def login_and_issue_token(*credentials)
|
|
25
32
|
return unless (user = user_class.authenticate(*credentials))
|
|
26
33
|
|
data/lib/sorcery/jwt/version.rb
CHANGED
|
@@ -15,11 +15,14 @@ module Sorcery
|
|
|
15
15
|
attr_accessor :jwt_algorithm
|
|
16
16
|
# How long the session should be valid for in seconds. Will be set as the exp claim in the token.
|
|
17
17
|
attr_accessor :session_expiry
|
|
18
|
+
# Clock-skew tolerance in seconds applied when verifying exp. nil disables leeway.
|
|
19
|
+
attr_accessor :exp_leeway
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
base.sorcery_config.instance_eval do
|
|
21
23
|
@defaults[:@jwt_algorithm] = "HS256"
|
|
22
24
|
@defaults[:@session_expiry] = 60 * 60 * 24 * 7 * 2 # 2 weeks
|
|
25
|
+
@defaults[:@exp_leeway] = nil
|
|
23
26
|
|
|
24
27
|
reset!
|
|
25
28
|
end
|
|
@@ -30,15 +33,33 @@ module Sorcery
|
|
|
30
33
|
end
|
|
31
34
|
|
|
32
35
|
module ClassMethods
|
|
36
|
+
# Encodes a JWT for a user, adding the exp and iat claims.
|
|
37
|
+
# Any claim in the payload except exp and iat is preserved.
|
|
38
|
+
#
|
|
39
|
+
# @param payload [Hash] claims to encode; must include "id" and "email"
|
|
40
|
+
# for the token to authenticate via the controller submodule
|
|
41
|
+
# @return [String] the signed JWT
|
|
33
42
|
def issue_token(payload)
|
|
34
|
-
|
|
43
|
+
now = Time.now.to_i
|
|
44
|
+
exp_payload = payload.merge(iat: now, exp: now + @sorcery_config.session_expiry)
|
|
35
45
|
JWT.encode(exp_payload, @sorcery_config.jwt_secret, @sorcery_config.jwt_algorithm)
|
|
36
46
|
end
|
|
37
47
|
|
|
48
|
+
# Decodes and verifies a JWT with the configured secret and algorithm.
|
|
49
|
+
#
|
|
50
|
+
# @param token [String, nil] the JWT
|
|
51
|
+
# @return [Array<(Hash, Hash)>] payload and header, as returned by jwt
|
|
52
|
+
# @raise [JWT::DecodeError] if the signature, algorithm, or exp fail
|
|
38
53
|
def decode_token(token)
|
|
39
|
-
|
|
54
|
+
options = { algorithm: @sorcery_config.jwt_algorithm }
|
|
55
|
+
options[:exp_leeway] = @sorcery_config.exp_leeway if @sorcery_config.exp_leeway
|
|
56
|
+
JWT.decode(token, @sorcery_config.jwt_secret, true, options)
|
|
40
57
|
end
|
|
41
58
|
|
|
59
|
+
# Returns whether a JWT is validly signed and unexpired.
|
|
60
|
+
#
|
|
61
|
+
# @param token [String, nil]
|
|
62
|
+
# @return [Boolean]
|
|
42
63
|
def token_valid?(token)
|
|
43
64
|
!!decode_token(token)
|
|
44
65
|
rescue JWT::DecodeError, JWT::ExpiredSignature
|
data/sorcery-jwt.gemspec
CHANGED
|
@@ -16,6 +16,8 @@ Gem::Specification.new do |spec|
|
|
|
16
16
|
spec.metadata["homepage_uri"] = spec.homepage
|
|
17
17
|
spec.metadata["source_code_uri"] = spec.homepage
|
|
18
18
|
spec.metadata["changelog_uri"] = "#{spec.homepage}/CHANGELOG.md"
|
|
19
|
+
spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
|
|
20
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
|
19
21
|
|
|
20
22
|
spec.required_ruby_version = ">= 3.0"
|
|
21
23
|
|
|
@@ -32,9 +34,12 @@ Gem::Specification.new do |spec|
|
|
|
32
34
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
33
35
|
spec.require_paths = ["lib"]
|
|
34
36
|
|
|
37
|
+
spec.add_development_dependency "activerecord", "~> 8.0"
|
|
38
|
+
spec.add_development_dependency "rails", "~> 8.0"
|
|
35
39
|
spec.add_development_dependency "rake", "~> 13.0"
|
|
36
40
|
spec.add_development_dependency "rspec", "~> 3.0"
|
|
41
|
+
spec.add_development_dependency "sqlite3", "~> 2.0"
|
|
37
42
|
|
|
38
43
|
spec.add_runtime_dependency "jwt", ">= 1.0", "< 3.0"
|
|
39
|
-
spec.add_runtime_dependency "sorcery", ">= 0.
|
|
44
|
+
spec.add_runtime_dependency "sorcery", ">= 0.16.5", "< 0.19"
|
|
40
45
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sorcery-jwt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Hayden Luckenbach
|
|
@@ -9,6 +9,34 @@ bindir: exe
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: activerecord
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '8.0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '8.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rails
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '8.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '8.0'
|
|
12
40
|
- !ruby/object:Gem::Dependency
|
|
13
41
|
name: rake
|
|
14
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -37,6 +65,20 @@ dependencies:
|
|
|
37
65
|
- - "~>"
|
|
38
66
|
- !ruby/object:Gem::Version
|
|
39
67
|
version: '3.0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: sqlite3
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '2.0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '2.0'
|
|
40
82
|
- !ruby/object:Gem::Dependency
|
|
41
83
|
name: jwt
|
|
42
84
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -63,20 +105,20 @@ dependencies:
|
|
|
63
105
|
requirements:
|
|
64
106
|
- - ">="
|
|
65
107
|
- !ruby/object:Gem::Version
|
|
66
|
-
version:
|
|
108
|
+
version: 0.16.5
|
|
67
109
|
- - "<"
|
|
68
110
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: '0.
|
|
111
|
+
version: '0.19'
|
|
70
112
|
type: :runtime
|
|
71
113
|
prerelease: false
|
|
72
114
|
version_requirements: !ruby/object:Gem::Requirement
|
|
73
115
|
requirements:
|
|
74
116
|
- - ">="
|
|
75
117
|
- !ruby/object:Gem::Version
|
|
76
|
-
version:
|
|
118
|
+
version: 0.16.5
|
|
77
119
|
- - "<"
|
|
78
120
|
- !ruby/object:Gem::Version
|
|
79
|
-
version: '0.
|
|
121
|
+
version: '0.19'
|
|
80
122
|
description: Adds JWT issuance and authentication to the Sorcery authentication library,
|
|
81
123
|
for API-only Rails apps.
|
|
82
124
|
executables: []
|
|
@@ -86,16 +128,22 @@ files:
|
|
|
86
128
|
- ".github/workflows/ci.yml"
|
|
87
129
|
- ".gitignore"
|
|
88
130
|
- ".rspec"
|
|
131
|
+
- ".ruby-version"
|
|
89
132
|
- CHANGELOG.md
|
|
90
133
|
- CODE_OF_CONDUCT.md
|
|
91
134
|
- Gemfile
|
|
92
135
|
- Gemfile.lock
|
|
93
136
|
- LICENSE.txt
|
|
94
|
-
- PLAN.md
|
|
95
137
|
- README.md
|
|
96
138
|
- Rakefile
|
|
97
139
|
- bin/console
|
|
98
140
|
- bin/setup
|
|
141
|
+
- gemfiles/sorcery_0.16.5.gemfile
|
|
142
|
+
- gemfiles/sorcery_0.16.5.gemfile.lock
|
|
143
|
+
- gemfiles/sorcery_0.17.0.gemfile
|
|
144
|
+
- gemfiles/sorcery_0.17.0.gemfile.lock
|
|
145
|
+
- gemfiles/sorcery_0.18.0.gemfile
|
|
146
|
+
- gemfiles/sorcery_0.18.0.gemfile.lock
|
|
99
147
|
- lib/sorcery/controller/submodules/jwt.rb
|
|
100
148
|
- lib/sorcery/jwt.rb
|
|
101
149
|
- lib/sorcery/jwt/version.rb
|
|
@@ -109,6 +157,8 @@ metadata:
|
|
|
109
157
|
homepage_uri: https://github.com/hayfever/sorcery-jwt
|
|
110
158
|
source_code_uri: https://github.com/hayfever/sorcery-jwt
|
|
111
159
|
changelog_uri: https://github.com/hayfever/sorcery-jwt/CHANGELOG.md
|
|
160
|
+
bug_tracker_uri: https://github.com/hayfever/sorcery-jwt/issues
|
|
161
|
+
rubygems_mfa_required: 'true'
|
|
112
162
|
rdoc_options: []
|
|
113
163
|
require_paths:
|
|
114
164
|
- lib
|
data/PLAN.md
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# Sorcery::Jwt — Completion plan (1.0.0, no rewrite)
|
|
2
|
-
|
|
3
|
-
Goal: ship 1.0.0 = the **existing API**, bug-fixed, tested, CI'd, compatible
|
|
4
|
-
with current sorcery. No architectural changes. Everything that would break
|
|
5
|
-
the public API is deferred (§5).
|
|
6
|
-
|
|
7
|
-
Public API frozen as-is (from `0.1.13`):
|
|
8
|
-
`issue_token(payload)` · `decode_token(token)` · `token_valid?(token)` ·
|
|
9
|
-
`login_from_jwt` (login source) · `login_and_issue_token(*credentials)` ·
|
|
10
|
-
token claims `id` + `email` · config: `jwt_secret`, `jwt_algorithm`,
|
|
11
|
-
`session_expiry`.
|
|
12
|
-
|
|
13
|
-
Current version `0.1.13`. Target `1.0.0`. Est. **~3 days**.
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## Phase 0 — Environment & packaging *(~0.5 day)*
|
|
18
|
-
|
|
19
|
-
- [ ] Install Ruby 3.2+ (none on this machine).
|
|
20
|
-
- [ ] Refresh `Gemfile.lock` on modern Bundler; drop `spec.add_development_dependency "bundler"`.
|
|
21
|
-
- [ ] Fill gemspec: `authors`, `email`, `description`, `metadata[...]`
|
|
22
|
-
(`homepage_uri`, `source_code_uri`, `changelog_uri`).
|
|
23
|
-
- [ ] Dependency check: gemspec allows `sorcery (>= 0.13, < 0.17)` and
|
|
24
|
-
`jwt (>= 1.0, < 3.0)`. Latest sorcery is **0.18.0** (Dec 2025, needs
|
|
25
|
-
Ruby ≥ 3.2). Plan: test 0.16.5 / 0.17 / 0.18, widen the range to what
|
|
26
|
-
CI proves. Keep `jwt < 3.0` unless 3.x is proven stable.
|
|
27
|
-
|
|
28
|
-
## Phase 1 — Bug fixes, API unchanged *(~0.5 day)*
|
|
29
|
-
|
|
30
|
-
All fixes are in-place; no caller-visible changes except corrected behavior.
|
|
31
|
-
|
|
32
|
-
- [ ] **Auth bypass** (`login_from_jwt`): `decoded_token.first.slice("id",
|
|
33
|
-
"email")` can be `{}` for a validly-signed token → `find_by({})`
|
|
34
|
-
returns the first user in the table. Fix: reject empty slice before
|
|
35
|
-
lookup (~2 lines). This is the only security-critical item.
|
|
36
|
-
- [ ] `token_valid?`: `.present?` is an undeclared ActiveSupport dependency.
|
|
37
|
-
Replace with a plain truthy check; add spec proving it works without
|
|
38
|
-
ActiveSupport loaded.
|
|
39
|
-
- [ ] Failed JWT login sets `@current_user = false` → `nil` (sorcery
|
|
40
|
-
convention).
|
|
41
|
-
- [ ] Keep the `JWT::ExpiredSignature` rescue clause (redundant on jwt 2.x,
|
|
42
|
-
correct on 1.x — harmless either way).
|
|
43
|
-
|
|
44
|
-
## Phase 2 — Test suite *(~1 day, the long pole)*
|
|
45
|
-
|
|
46
|
-
- [ ] PORO test doubles, not a dummy Rails app: stub `User#find_by` /
|
|
47
|
-
`authenticate`, fake controller with stubbed `request.headers`.
|
|
48
|
-
Time-box **half a day**; if sorcery's Model included-hook fights a
|
|
49
|
-
PORO, mirror sorcery's own spec helper pattern instead.
|
|
50
|
-
- [ ] Specs (all public methods + failure modes):
|
|
51
|
-
- issue → decode round-trip; `exp` set and enforced
|
|
52
|
-
- wrong secret / wrong algorithm → rejected
|
|
53
|
-
- **missing claims → no login** (bypass regression test)
|
|
54
|
-
- valid sig, user not in DB → no login
|
|
55
|
-
- `token_valid?` without ActiveSupport
|
|
56
|
-
- `login_and_issue_token` bad credentials → nil, no `current_user`
|
|
57
|
-
- missing/malformed Authorization header → no login, no exception
|
|
58
|
-
- [ ] **Ship `0.2.0`** here: tested + security fix for the existing user base
|
|
59
|
-
(95K downloads on 0.1.13), zero API break. Don't hold it for 1.0.
|
|
60
|
-
|
|
61
|
-
## Phase 3 — Compat verification + CI *(~0.5 day)*
|
|
62
|
-
|
|
63
|
-
- [ ] Replace `.travis.yml` with GitHub Actions: `bundle exec rspec` on
|
|
64
|
-
Ruby 3.2 / 3.3 / 3.4 × sorcery 0.16.5 / 0.17 / 0.18 (or appraisal).
|
|
65
|
-
- [ ] Fix whatever breaks on sorcery 0.17/0.18 (candidate:
|
|
66
|
-
`Config.login_sources` internals, `Time.now` usage).
|
|
67
|
-
- [ ] Set final dependency ranges from what CI proves green.
|
|
68
|
-
|
|
69
|
-
## Phase 4 — Docs + release *(~0.5 day)*
|
|
70
|
-
|
|
71
|
-
- [ ] README: claim contract (`id` + `email` required in payload), config
|
|
72
|
-
reference, security notes (no built-in revocation — link
|
|
73
|
-
waiting-for-dev revocation strategies), upstream note (sorcery v1
|
|
74
|
-
plans an official JWT plugin).
|
|
75
|
-
- [ ] `CHANGELOG.md` 0.1.13 → 1.0.0: framing = same API, bugs fixed, suite +
|
|
76
|
-
CI added, current sorcery supported. No breaking changes from 0.1.13.
|
|
77
|
-
- [ ] `bundle exec rake build`, install locally, smoke test.
|
|
78
|
-
- [ ] Tag `v1.0.0`, `gem push` (hayfever owns the rubygems slot).
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
## 5. Explicitly deferred (API-breaking — out of scope for 1.0)
|
|
83
|
-
|
|
84
|
-
From the earlier review; revisit only if upstream v1 stalls indefinitely:
|
|
85
|
-
|
|
86
|
-
- `token_version` revocation (logout / password-change invalidation)
|
|
87
|
-
- Refresh tokens with rotation + reuse detection
|
|
88
|
-
- `sub` / `iat` / `jti` claims, `exp` leeway, email decoupling
|
|
89
|
-
- `authenticate_from_token` encapsulation (decode contract stays as-is)
|
|
90
|
-
|
|
91
|
-
Endgame note: upstream sorcery is active (commits through mid-2026, V1
|
|
92
|
-
roadmap on main) and plans an official `sorcery-jwt` plugin for v1 — same
|
|
93
|
-
gem name we own. After 1.0, talk to maintainers (history in
|
|
94
|
-
sorcery-rework#9) about handover vs. parallel.
|