@adonisjs/auth 10.0.0-next.1 → 10.0.0-next.3
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.
- package/build/auth_manager-BMz_OJXq.js +129 -0
- package/build/debug-Ckko95-M.js +3 -0
- package/build/errors-BQxhZmkE.js +128 -0
- package/build/index.js +59 -100
- package/build/modules/access_tokens_guard/main.js +647 -1309
- package/build/modules/access_tokens_guard/types.js +1 -0
- package/build/modules/basic_auth_guard/main.js +106 -236
- package/build/modules/basic_auth_guard/types.js +1 -0
- package/build/modules/session_guard/main.js +377 -966
- package/build/modules/session_guard/types.js +1 -0
- package/build/providers/auth_provider.js +16 -40
- package/build/services/auth.js +3 -8
- package/build/src/debug.d.ts +1 -1
- package/build/src/middleware/initialize_auth_middleware.js +6 -24
- package/build/src/mixins/lucid.d.ts +4 -4
- package/build/src/mixins/lucid.js +43 -93
- package/build/src/plugins/japa/api_client.js +43 -56
- package/build/src/plugins/japa/browser_client.js +45 -64
- package/build/src/types.js +1 -0
- package/build/symbols-Ct253Khf.js +8 -0
- package/package.json +40 -37
- package/build/chunk-2VRS2VHB.js +0 -7
- package/build/chunk-MSPAYMZE.js +0 -351
- package/build/chunk-S5G5RTJX.js +0 -236
- package/build/chunk-UXA4FHST.js +0 -19
|
@@ -1,1324 +1,662 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
} from "../../chunk-S5G5RTJX.js";
|
|
4
|
-
import "../../chunk-UXA4FHST.js";
|
|
5
|
-
|
|
6
|
-
// modules/access_tokens_guard/access_token.ts
|
|
7
|
-
import { createHash } from "crypto";
|
|
8
|
-
import string from "@adonisjs/core/helpers/string";
|
|
1
|
+
import { n as E_UNAUTHORIZED_ACCESS } from "../../errors-BQxhZmkE.js";
|
|
2
|
+
import "../../symbols-Ct253Khf.js";
|
|
9
3
|
import { RuntimeException } from "@adonisjs/core/exceptions";
|
|
4
|
+
import { inspect } from "node:util";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
import string from "@adonisjs/core/helpers/string";
|
|
10
7
|
import { Secret, base64, safeEqual } from "@adonisjs/core/helpers";
|
|
11
|
-
|
|
12
|
-
// modules/access_tokens_guard/crc32.ts
|
|
13
8
|
var CRC32 = class {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
* @example
|
|
304
|
-
* const crc = new CRC32()
|
|
305
|
-
* const checksum = crc.calculate('hello-world')
|
|
306
|
-
* console.log('CRC32:', checksum)
|
|
307
|
-
*/
|
|
308
|
-
calculate(input) {
|
|
309
|
-
return this.forString(input);
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Calculate CRC32 checksum for a string
|
|
313
|
-
*
|
|
314
|
-
* @param input - The string to process
|
|
315
|
-
*
|
|
316
|
-
* @example
|
|
317
|
-
* const crc = new CRC32()
|
|
318
|
-
* const result = crc.forString('test-string')
|
|
319
|
-
*/
|
|
320
|
-
forString(input) {
|
|
321
|
-
const bytes = this.#strToBytes(input);
|
|
322
|
-
return this.forBytes(bytes);
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Calculate CRC32 checksum for byte array
|
|
326
|
-
*
|
|
327
|
-
* @param bytes - The byte array to process
|
|
328
|
-
* @param accumulator - Optional accumulator for chained calculations
|
|
329
|
-
*
|
|
330
|
-
* @example
|
|
331
|
-
* const crc = new CRC32()
|
|
332
|
-
* const bytes = new TextEncoder().encode('hello')
|
|
333
|
-
* const result = crc.forBytes(bytes)
|
|
334
|
-
*/
|
|
335
|
-
forBytes(bytes, accumulator) {
|
|
336
|
-
const crc = this.#calculateBytes(bytes, accumulator);
|
|
337
|
-
return this.#crcToUint(crc);
|
|
338
|
-
}
|
|
9
|
+
#lookupTable = [
|
|
10
|
+
0,
|
|
11
|
+
1996959894,
|
|
12
|
+
3993919788,
|
|
13
|
+
2567524794,
|
|
14
|
+
124634137,
|
|
15
|
+
1886057615,
|
|
16
|
+
3915621685,
|
|
17
|
+
2657392035,
|
|
18
|
+
249268274,
|
|
19
|
+
2044508324,
|
|
20
|
+
3772115230,
|
|
21
|
+
2547177864,
|
|
22
|
+
162941995,
|
|
23
|
+
2125561021,
|
|
24
|
+
3887607047,
|
|
25
|
+
2428444049,
|
|
26
|
+
498536548,
|
|
27
|
+
1789927666,
|
|
28
|
+
4089016648,
|
|
29
|
+
2227061214,
|
|
30
|
+
450548861,
|
|
31
|
+
1843258603,
|
|
32
|
+
4107580753,
|
|
33
|
+
2211677639,
|
|
34
|
+
325883990,
|
|
35
|
+
1684777152,
|
|
36
|
+
4251122042,
|
|
37
|
+
2321926636,
|
|
38
|
+
335633487,
|
|
39
|
+
1661365465,
|
|
40
|
+
4195302755,
|
|
41
|
+
2366115317,
|
|
42
|
+
997073096,
|
|
43
|
+
1281953886,
|
|
44
|
+
3579855332,
|
|
45
|
+
2724688242,
|
|
46
|
+
1006888145,
|
|
47
|
+
1258607687,
|
|
48
|
+
3524101629,
|
|
49
|
+
2768942443,
|
|
50
|
+
901097722,
|
|
51
|
+
1119000684,
|
|
52
|
+
3686517206,
|
|
53
|
+
2898065728,
|
|
54
|
+
853044451,
|
|
55
|
+
1172266101,
|
|
56
|
+
3705015759,
|
|
57
|
+
2882616665,
|
|
58
|
+
651767980,
|
|
59
|
+
1373503546,
|
|
60
|
+
3369554304,
|
|
61
|
+
3218104598,
|
|
62
|
+
565507253,
|
|
63
|
+
1454621731,
|
|
64
|
+
3485111705,
|
|
65
|
+
3099436303,
|
|
66
|
+
671266974,
|
|
67
|
+
1594198024,
|
|
68
|
+
3322730930,
|
|
69
|
+
2970347812,
|
|
70
|
+
795835527,
|
|
71
|
+
1483230225,
|
|
72
|
+
3244367275,
|
|
73
|
+
3060149565,
|
|
74
|
+
1994146192,
|
|
75
|
+
31158534,
|
|
76
|
+
2563907772,
|
|
77
|
+
4023717930,
|
|
78
|
+
1907459465,
|
|
79
|
+
112637215,
|
|
80
|
+
2680153253,
|
|
81
|
+
3904427059,
|
|
82
|
+
2013776290,
|
|
83
|
+
251722036,
|
|
84
|
+
2517215374,
|
|
85
|
+
3775830040,
|
|
86
|
+
2137656763,
|
|
87
|
+
141376813,
|
|
88
|
+
2439277719,
|
|
89
|
+
3865271297,
|
|
90
|
+
1802195444,
|
|
91
|
+
476864866,
|
|
92
|
+
2238001368,
|
|
93
|
+
4066508878,
|
|
94
|
+
1812370925,
|
|
95
|
+
453092731,
|
|
96
|
+
2181625025,
|
|
97
|
+
4111451223,
|
|
98
|
+
1706088902,
|
|
99
|
+
314042704,
|
|
100
|
+
2344532202,
|
|
101
|
+
4240017532,
|
|
102
|
+
1658658271,
|
|
103
|
+
366619977,
|
|
104
|
+
2362670323,
|
|
105
|
+
4224994405,
|
|
106
|
+
1303535960,
|
|
107
|
+
984961486,
|
|
108
|
+
2747007092,
|
|
109
|
+
3569037538,
|
|
110
|
+
1256170817,
|
|
111
|
+
1037604311,
|
|
112
|
+
2765210733,
|
|
113
|
+
3554079995,
|
|
114
|
+
1131014506,
|
|
115
|
+
879679996,
|
|
116
|
+
2909243462,
|
|
117
|
+
3663771856,
|
|
118
|
+
1141124467,
|
|
119
|
+
855842277,
|
|
120
|
+
2852801631,
|
|
121
|
+
3708648649,
|
|
122
|
+
1342533948,
|
|
123
|
+
654459306,
|
|
124
|
+
3188396048,
|
|
125
|
+
3373015174,
|
|
126
|
+
1466479909,
|
|
127
|
+
544179635,
|
|
128
|
+
3110523913,
|
|
129
|
+
3462522015,
|
|
130
|
+
1591671054,
|
|
131
|
+
702138776,
|
|
132
|
+
2966460450,
|
|
133
|
+
3352799412,
|
|
134
|
+
1504918807,
|
|
135
|
+
783551873,
|
|
136
|
+
3082640443,
|
|
137
|
+
3233442989,
|
|
138
|
+
3988292384,
|
|
139
|
+
2596254646,
|
|
140
|
+
62317068,
|
|
141
|
+
1957810842,
|
|
142
|
+
3939845945,
|
|
143
|
+
2647816111,
|
|
144
|
+
81470997,
|
|
145
|
+
1943803523,
|
|
146
|
+
3814918930,
|
|
147
|
+
2489596804,
|
|
148
|
+
225274430,
|
|
149
|
+
2053790376,
|
|
150
|
+
3826175755,
|
|
151
|
+
2466906013,
|
|
152
|
+
167816743,
|
|
153
|
+
2097651377,
|
|
154
|
+
4027552580,
|
|
155
|
+
2265490386,
|
|
156
|
+
503444072,
|
|
157
|
+
1762050814,
|
|
158
|
+
4150417245,
|
|
159
|
+
2154129355,
|
|
160
|
+
426522225,
|
|
161
|
+
1852507879,
|
|
162
|
+
4275313526,
|
|
163
|
+
2312317920,
|
|
164
|
+
282753626,
|
|
165
|
+
1742555852,
|
|
166
|
+
4189708143,
|
|
167
|
+
2394877945,
|
|
168
|
+
397917763,
|
|
169
|
+
1622183637,
|
|
170
|
+
3604390888,
|
|
171
|
+
2714866558,
|
|
172
|
+
953729732,
|
|
173
|
+
1340076626,
|
|
174
|
+
3518719985,
|
|
175
|
+
2797360999,
|
|
176
|
+
1068828381,
|
|
177
|
+
1219638859,
|
|
178
|
+
3624741850,
|
|
179
|
+
2936675148,
|
|
180
|
+
906185462,
|
|
181
|
+
1090812512,
|
|
182
|
+
3747672003,
|
|
183
|
+
2825379669,
|
|
184
|
+
829329135,
|
|
185
|
+
1181335161,
|
|
186
|
+
3412177804,
|
|
187
|
+
3160834842,
|
|
188
|
+
628085408,
|
|
189
|
+
1382605366,
|
|
190
|
+
3423369109,
|
|
191
|
+
3138078467,
|
|
192
|
+
570562233,
|
|
193
|
+
1426400815,
|
|
194
|
+
3317316542,
|
|
195
|
+
2998733608,
|
|
196
|
+
733239954,
|
|
197
|
+
1555261956,
|
|
198
|
+
3268935591,
|
|
199
|
+
3050360625,
|
|
200
|
+
752459403,
|
|
201
|
+
1541320221,
|
|
202
|
+
2607071920,
|
|
203
|
+
3965973030,
|
|
204
|
+
1969922972,
|
|
205
|
+
40735498,
|
|
206
|
+
2617837225,
|
|
207
|
+
3943577151,
|
|
208
|
+
1913087877,
|
|
209
|
+
83908371,
|
|
210
|
+
2512341634,
|
|
211
|
+
3803740692,
|
|
212
|
+
2075208622,
|
|
213
|
+
213261112,
|
|
214
|
+
2463272603,
|
|
215
|
+
3855990285,
|
|
216
|
+
2094854071,
|
|
217
|
+
198958881,
|
|
218
|
+
2262029012,
|
|
219
|
+
4057260610,
|
|
220
|
+
1759359992,
|
|
221
|
+
534414190,
|
|
222
|
+
2176718541,
|
|
223
|
+
4139329115,
|
|
224
|
+
1873836001,
|
|
225
|
+
414664567,
|
|
226
|
+
2282248934,
|
|
227
|
+
4279200368,
|
|
228
|
+
1711684554,
|
|
229
|
+
285281116,
|
|
230
|
+
2405801727,
|
|
231
|
+
4167216745,
|
|
232
|
+
1634467795,
|
|
233
|
+
376229701,
|
|
234
|
+
2685067896,
|
|
235
|
+
3608007406,
|
|
236
|
+
1308918612,
|
|
237
|
+
956543938,
|
|
238
|
+
2808555105,
|
|
239
|
+
3495958263,
|
|
240
|
+
1231636301,
|
|
241
|
+
1047427035,
|
|
242
|
+
2932959818,
|
|
243
|
+
3654703836,
|
|
244
|
+
1088359270,
|
|
245
|
+
936918e3,
|
|
246
|
+
2847714899,
|
|
247
|
+
3736837829,
|
|
248
|
+
1202900863,
|
|
249
|
+
817233897,
|
|
250
|
+
3183342108,
|
|
251
|
+
3401237130,
|
|
252
|
+
1404277552,
|
|
253
|
+
615818150,
|
|
254
|
+
3134207493,
|
|
255
|
+
3453421203,
|
|
256
|
+
1423857449,
|
|
257
|
+
601450431,
|
|
258
|
+
3009837614,
|
|
259
|
+
3294710456,
|
|
260
|
+
1567103746,
|
|
261
|
+
711928724,
|
|
262
|
+
3020668471,
|
|
263
|
+
3272380065,
|
|
264
|
+
1510334235,
|
|
265
|
+
755167117
|
|
266
|
+
];
|
|
267
|
+
#initialCRC = 4294967295;
|
|
268
|
+
#calculateBytes(bytes, accumulator) {
|
|
269
|
+
let crc = accumulator || this.#initialCRC;
|
|
270
|
+
for (const byte of bytes) {
|
|
271
|
+
const tableIndex = (crc ^ byte) & 255;
|
|
272
|
+
const tableVal = this.#lookupTable[tableIndex];
|
|
273
|
+
crc = crc >>> 8 ^ tableVal;
|
|
274
|
+
}
|
|
275
|
+
return crc;
|
|
276
|
+
}
|
|
277
|
+
#crcToUint(crc) {
|
|
278
|
+
return this.#toUint32(crc ^ 4294967295);
|
|
279
|
+
}
|
|
280
|
+
#strToBytes(input) {
|
|
281
|
+
return new TextEncoder().encode(input);
|
|
282
|
+
}
|
|
283
|
+
#toUint32(num) {
|
|
284
|
+
if (num >= 0) return num;
|
|
285
|
+
return 4294967295 - num * -1 + 1;
|
|
286
|
+
}
|
|
287
|
+
calculate(input) {
|
|
288
|
+
return this.forString(input);
|
|
289
|
+
}
|
|
290
|
+
forString(input) {
|
|
291
|
+
const bytes = this.#strToBytes(input);
|
|
292
|
+
return this.forBytes(bytes);
|
|
293
|
+
}
|
|
294
|
+
forBytes(bytes, accumulator) {
|
|
295
|
+
const crc = this.#calculateBytes(bytes, accumulator);
|
|
296
|
+
return this.#crcToUint(crc);
|
|
297
|
+
}
|
|
339
298
|
};
|
|
340
|
-
|
|
341
|
-
// modules/access_tokens_guard/access_token.ts
|
|
342
299
|
var AccessToken = class {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
* Reference to the user id for whom the token
|
|
432
|
-
* is generated.
|
|
433
|
-
*/
|
|
434
|
-
tokenableId;
|
|
435
|
-
/**
|
|
436
|
-
* The value is a public representation of a token. It is created
|
|
437
|
-
* by combining the "identifier"."secret"
|
|
438
|
-
*/
|
|
439
|
-
value;
|
|
440
|
-
/**
|
|
441
|
-
* Recognizable name for the token
|
|
442
|
-
*/
|
|
443
|
-
name;
|
|
444
|
-
/**
|
|
445
|
-
* A unique type to identify a bucket of tokens inside the
|
|
446
|
-
* storage layer.
|
|
447
|
-
*/
|
|
448
|
-
type;
|
|
449
|
-
/**
|
|
450
|
-
* Hash is computed from the seed to later verify the validity
|
|
451
|
-
* of seed
|
|
452
|
-
*/
|
|
453
|
-
hash;
|
|
454
|
-
/**
|
|
455
|
-
* Date/time when the token instance was created
|
|
456
|
-
*/
|
|
457
|
-
createdAt;
|
|
458
|
-
/**
|
|
459
|
-
* Date/time when the token was updated
|
|
460
|
-
*/
|
|
461
|
-
updatedAt;
|
|
462
|
-
/**
|
|
463
|
-
* Timestamp at which the token was used for authentication
|
|
464
|
-
*/
|
|
465
|
-
lastUsedAt;
|
|
466
|
-
/**
|
|
467
|
-
* Timestamp at which the token will expire
|
|
468
|
-
*/
|
|
469
|
-
expiresAt;
|
|
470
|
-
/**
|
|
471
|
-
* An array of abilities the token can perform. The abilities
|
|
472
|
-
* is an array of abritary string values
|
|
473
|
-
*/
|
|
474
|
-
abilities;
|
|
475
|
-
/**
|
|
476
|
-
* Creates a new AccessToken instance
|
|
477
|
-
*
|
|
478
|
-
* @param attributes - Token attributes including identifier, user ID, type, hash, etc.
|
|
479
|
-
*
|
|
480
|
-
* @example
|
|
481
|
-
* const token = new AccessToken({
|
|
482
|
-
* identifier: 1,
|
|
483
|
-
* tokenableId: 123,
|
|
484
|
-
* type: 'api',
|
|
485
|
-
* hash: 'sha256hash',
|
|
486
|
-
* createdAt: new Date(),
|
|
487
|
-
* updatedAt: new Date(),
|
|
488
|
-
* lastUsedAt: null,
|
|
489
|
-
* expiresAt: new Date(Date.now() + 86400000),
|
|
490
|
-
* name: 'Mobile App Token',
|
|
491
|
-
* abilities: ['read:posts', 'write:posts']
|
|
492
|
-
* })
|
|
493
|
-
*/
|
|
494
|
-
constructor(attributes) {
|
|
495
|
-
this.identifier = attributes.identifier;
|
|
496
|
-
this.tokenableId = attributes.tokenableId;
|
|
497
|
-
this.name = attributes.name;
|
|
498
|
-
this.hash = attributes.hash;
|
|
499
|
-
this.type = attributes.type;
|
|
500
|
-
this.createdAt = attributes.createdAt;
|
|
501
|
-
this.updatedAt = attributes.updatedAt;
|
|
502
|
-
this.expiresAt = attributes.expiresAt;
|
|
503
|
-
this.lastUsedAt = attributes.lastUsedAt;
|
|
504
|
-
this.abilities = attributes.abilities || ["*"];
|
|
505
|
-
if (attributes.secret) {
|
|
506
|
-
if (!attributes.prefix) {
|
|
507
|
-
throw new RuntimeException("Cannot compute token value without the prefix");
|
|
508
|
-
}
|
|
509
|
-
this.value = new Secret(
|
|
510
|
-
`${attributes.prefix}${base64.urlEncode(String(this.identifier))}.${base64.urlEncode(
|
|
511
|
-
attributes.secret.release()
|
|
512
|
-
)}`
|
|
513
|
-
);
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
/**
|
|
517
|
-
* Check if the token allows the given ability.
|
|
518
|
-
*
|
|
519
|
-
* @param ability - The ability to check
|
|
520
|
-
*
|
|
521
|
-
* @example
|
|
522
|
-
* if (token.allows('read:posts')) {
|
|
523
|
-
* console.log('User can read posts')
|
|
524
|
-
* }
|
|
525
|
-
*/
|
|
526
|
-
allows(ability) {
|
|
527
|
-
return this.abilities.includes(ability) || this.abilities.includes("*");
|
|
528
|
-
}
|
|
529
|
-
/**
|
|
530
|
-
* Check if the token denies the ability.
|
|
531
|
-
*
|
|
532
|
-
* @param ability - The ability to check
|
|
533
|
-
*
|
|
534
|
-
* @example
|
|
535
|
-
* if (token.denies('delete:posts')) {
|
|
536
|
-
* console.log('User cannot delete posts')
|
|
537
|
-
* }
|
|
538
|
-
*/
|
|
539
|
-
denies(ability) {
|
|
540
|
-
return !this.abilities.includes(ability) && !this.abilities.includes("*");
|
|
541
|
-
}
|
|
542
|
-
/**
|
|
543
|
-
* Authorize ability access using the current access token
|
|
544
|
-
*
|
|
545
|
-
* @param ability - The ability to authorize
|
|
546
|
-
*
|
|
547
|
-
* @throws {E_UNAUTHORIZED_ACCESS} When the token denies the ability
|
|
548
|
-
*
|
|
549
|
-
* @example
|
|
550
|
-
* token.authorize('write:posts') // Throws if not allowed
|
|
551
|
-
* console.log('Authorization successful')
|
|
552
|
-
*/
|
|
553
|
-
authorize(ability) {
|
|
554
|
-
if (this.denies(ability)) {
|
|
555
|
-
throw new E_UNAUTHORIZED_ACCESS("Unauthorized access", { guardDriverName: "access_tokens" });
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
/**
|
|
559
|
-
* Check if the token has been expired. Verifies
|
|
560
|
-
* the "expiresAt" timestamp with the current
|
|
561
|
-
* date.
|
|
562
|
-
*
|
|
563
|
-
* Tokens with no expiry never expire
|
|
564
|
-
*
|
|
565
|
-
* @example
|
|
566
|
-
* if (token.isExpired()) {
|
|
567
|
-
* console.log('Token has expired')
|
|
568
|
-
* } else {
|
|
569
|
-
* console.log('Token is still valid')
|
|
570
|
-
* }
|
|
571
|
-
*/
|
|
572
|
-
isExpired() {
|
|
573
|
-
if (!this.expiresAt) {
|
|
574
|
-
return false;
|
|
575
|
-
}
|
|
576
|
-
return this.expiresAt < /* @__PURE__ */ new Date();
|
|
577
|
-
}
|
|
578
|
-
/**
|
|
579
|
-
* Verifies the value of a token against the pre-defined hash
|
|
580
|
-
*
|
|
581
|
-
* @param secret - The secret to verify against the stored hash
|
|
582
|
-
*
|
|
583
|
-
* @example
|
|
584
|
-
* const isValid = token.verify(new Secret('user-provided-secret'))
|
|
585
|
-
* if (isValid) {
|
|
586
|
-
* console.log('Token is valid')
|
|
587
|
-
* }
|
|
588
|
-
*/
|
|
589
|
-
verify(secret) {
|
|
590
|
-
const newHash = createHash("sha256").update(secret.release()).digest("hex");
|
|
591
|
-
return safeEqual(this.hash, newHash);
|
|
592
|
-
}
|
|
593
|
-
/**
|
|
594
|
-
* Converts the token to a JSON representation suitable for API responses
|
|
595
|
-
*
|
|
596
|
-
* @example
|
|
597
|
-
* const tokenData = token.toJSON()
|
|
598
|
-
* console.log(tokenData.type) // 'bearer'
|
|
599
|
-
* console.log(tokenData.token) // 'oat_abc123.def456'
|
|
600
|
-
*/
|
|
601
|
-
toJSON() {
|
|
602
|
-
return {
|
|
603
|
-
type: "bearer",
|
|
604
|
-
name: this.name,
|
|
605
|
-
token: this.value ? this.value.release() : void 0,
|
|
606
|
-
abilities: this.abilities,
|
|
607
|
-
lastUsedAt: this.lastUsedAt,
|
|
608
|
-
expiresAt: this.expiresAt
|
|
609
|
-
};
|
|
610
|
-
}
|
|
300
|
+
static decode(prefix, value) {
|
|
301
|
+
if (typeof value !== "string" || !value.startsWith(`${prefix}`)) return null;
|
|
302
|
+
const token = value.replace(/* @__PURE__ */ new RegExp(`^${prefix}`), "");
|
|
303
|
+
if (!token) return null;
|
|
304
|
+
const [identifier, ...tokenValue] = token.split(".");
|
|
305
|
+
if (!identifier || tokenValue.length === 0) return null;
|
|
306
|
+
const decodedIdentifier = base64.urlDecode(identifier);
|
|
307
|
+
const decodedSecret = base64.urlDecode(tokenValue.join("."));
|
|
308
|
+
if (!decodedIdentifier || !decodedSecret) return null;
|
|
309
|
+
return {
|
|
310
|
+
identifier: decodedIdentifier,
|
|
311
|
+
secret: new Secret(decodedSecret)
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
static createTransientToken(userId, size, expiresIn) {
|
|
315
|
+
let expiresAt;
|
|
316
|
+
if (expiresIn) {
|
|
317
|
+
expiresAt = /* @__PURE__ */ new Date();
|
|
318
|
+
expiresAt.setSeconds(expiresAt.getSeconds() + string.seconds.parse(expiresIn));
|
|
319
|
+
}
|
|
320
|
+
return {
|
|
321
|
+
userId,
|
|
322
|
+
expiresAt,
|
|
323
|
+
...this.seed(size)
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
static seed(size) {
|
|
327
|
+
const seed = string.random(size);
|
|
328
|
+
const secret = new Secret(`${seed}${new CRC32().calculate(seed)}`);
|
|
329
|
+
return {
|
|
330
|
+
secret,
|
|
331
|
+
hash: createHash("sha256").update(secret.release()).digest("hex")
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
identifier;
|
|
335
|
+
tokenableId;
|
|
336
|
+
value;
|
|
337
|
+
name;
|
|
338
|
+
type;
|
|
339
|
+
hash;
|
|
340
|
+
createdAt;
|
|
341
|
+
updatedAt;
|
|
342
|
+
lastUsedAt;
|
|
343
|
+
expiresAt;
|
|
344
|
+
abilities;
|
|
345
|
+
constructor(attributes) {
|
|
346
|
+
this.identifier = attributes.identifier;
|
|
347
|
+
this.tokenableId = attributes.tokenableId;
|
|
348
|
+
this.name = attributes.name;
|
|
349
|
+
this.hash = attributes.hash;
|
|
350
|
+
this.type = attributes.type;
|
|
351
|
+
this.createdAt = attributes.createdAt;
|
|
352
|
+
this.updatedAt = attributes.updatedAt;
|
|
353
|
+
this.expiresAt = attributes.expiresAt;
|
|
354
|
+
this.lastUsedAt = attributes.lastUsedAt;
|
|
355
|
+
this.abilities = attributes.abilities || ["*"];
|
|
356
|
+
if (attributes.secret) {
|
|
357
|
+
if (!attributes.prefix) throw new RuntimeException("Cannot compute token value without the prefix");
|
|
358
|
+
this.value = new Secret(`${attributes.prefix}${base64.urlEncode(String(this.identifier))}.${base64.urlEncode(attributes.secret.release())}`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
allows(ability) {
|
|
362
|
+
return this.abilities.includes(ability) || this.abilities.includes("*");
|
|
363
|
+
}
|
|
364
|
+
denies(ability) {
|
|
365
|
+
return !this.abilities.includes(ability) && !this.abilities.includes("*");
|
|
366
|
+
}
|
|
367
|
+
authorize(ability) {
|
|
368
|
+
if (this.denies(ability)) throw new E_UNAUTHORIZED_ACCESS("Unauthorized access", { guardDriverName: "access_tokens" });
|
|
369
|
+
}
|
|
370
|
+
isExpired() {
|
|
371
|
+
if (!this.expiresAt) return false;
|
|
372
|
+
return this.expiresAt < /* @__PURE__ */ new Date();
|
|
373
|
+
}
|
|
374
|
+
verify(secret) {
|
|
375
|
+
const newHash = createHash("sha256").update(secret.release()).digest("hex");
|
|
376
|
+
return safeEqual(this.hash, newHash);
|
|
377
|
+
}
|
|
378
|
+
toJSON() {
|
|
379
|
+
return {
|
|
380
|
+
type: "bearer",
|
|
381
|
+
name: this.name,
|
|
382
|
+
token: this.value ? this.value.release() : void 0,
|
|
383
|
+
abilities: this.abilities,
|
|
384
|
+
lastUsedAt: this.lastUsedAt,
|
|
385
|
+
expiresAt: this.expiresAt
|
|
386
|
+
};
|
|
387
|
+
}
|
|
611
388
|
};
|
|
612
|
-
|
|
613
|
-
// modules/access_tokens_guard/guard.ts
|
|
614
|
-
import { Secret as Secret2 } from "@adonisjs/core/helpers";
|
|
615
389
|
var AccessTokensGuard = class {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
guardName: this.#name,
|
|
691
|
-
error
|
|
692
|
-
});
|
|
693
|
-
return error;
|
|
694
|
-
}
|
|
695
|
-
/**
|
|
696
|
-
* Returns the bearer token from the request headers or fails
|
|
697
|
-
*/
|
|
698
|
-
#getBearerToken() {
|
|
699
|
-
const bearerToken = this.#ctx.request.header("authorization", "");
|
|
700
|
-
const [type, token] = bearerToken.split(" ");
|
|
701
|
-
if (!type || type.toLowerCase() !== "bearer" || !token) {
|
|
702
|
-
throw this.#authenticationFailed();
|
|
703
|
-
}
|
|
704
|
-
return token;
|
|
705
|
-
}
|
|
706
|
-
/**
|
|
707
|
-
* Returns an instance of the authenticated user. Or throws
|
|
708
|
-
* an exception if the request is not authenticated.
|
|
709
|
-
*
|
|
710
|
-
* @throws {E_UNAUTHORIZED_ACCESS} When user is not authenticated
|
|
711
|
-
*
|
|
712
|
-
* @example
|
|
713
|
-
* const user = guard.getUserOrFail()
|
|
714
|
-
* console.log('User ID:', user.id)
|
|
715
|
-
* console.log('Current token:', user.currentAccessToken.name)
|
|
716
|
-
*/
|
|
717
|
-
getUserOrFail() {
|
|
718
|
-
if (!this.user) {
|
|
719
|
-
throw new E_UNAUTHORIZED_ACCESS("Unauthorized access", {
|
|
720
|
-
guardDriverName: this.driverName
|
|
721
|
-
});
|
|
722
|
-
}
|
|
723
|
-
return this.user;
|
|
724
|
-
}
|
|
725
|
-
/**
|
|
726
|
-
* Authenticate the current HTTP request by verifying the bearer
|
|
727
|
-
* token or fails with an exception
|
|
728
|
-
*
|
|
729
|
-
* @throws {E_UNAUTHORIZED_ACCESS} When authentication fails
|
|
730
|
-
*
|
|
731
|
-
* @example
|
|
732
|
-
* try {
|
|
733
|
-
* const user = await guard.authenticate()
|
|
734
|
-
* console.log('Authenticated as:', user.email)
|
|
735
|
-
* console.log('Token abilities:', user.currentAccessToken.abilities)
|
|
736
|
-
* } catch (error) {
|
|
737
|
-
* console.log('Authentication failed')
|
|
738
|
-
* }
|
|
739
|
-
*/
|
|
740
|
-
async authenticate() {
|
|
741
|
-
if (this.authenticationAttempted) {
|
|
742
|
-
return this.getUserOrFail();
|
|
743
|
-
}
|
|
744
|
-
this.authenticationAttempted = true;
|
|
745
|
-
this.#emitter.emit("access_tokens_auth:authentication_attempted", {
|
|
746
|
-
ctx: this.#ctx,
|
|
747
|
-
guardName: this.#name
|
|
748
|
-
});
|
|
749
|
-
const bearerToken = new Secret2(this.#getBearerToken());
|
|
750
|
-
const token = await this.#userProvider.verifyToken(bearerToken);
|
|
751
|
-
if (!token) {
|
|
752
|
-
throw this.#authenticationFailed();
|
|
753
|
-
}
|
|
754
|
-
const providerUser = await this.#userProvider.findById(token.tokenableId);
|
|
755
|
-
if (!providerUser) {
|
|
756
|
-
throw this.#authenticationFailed();
|
|
757
|
-
}
|
|
758
|
-
this.isAuthenticated = true;
|
|
759
|
-
this.user = providerUser.getOriginal();
|
|
760
|
-
this.user.currentAccessToken = token;
|
|
761
|
-
this.#emitter.emit("access_tokens_auth:authentication_succeeded", {
|
|
762
|
-
ctx: this.#ctx,
|
|
763
|
-
token,
|
|
764
|
-
guardName: this.#name,
|
|
765
|
-
user: this.user
|
|
766
|
-
});
|
|
767
|
-
return this.user;
|
|
768
|
-
}
|
|
769
|
-
/**
|
|
770
|
-
* Create a token for a user (sign in)
|
|
771
|
-
*
|
|
772
|
-
* @param user - The user to create a token for
|
|
773
|
-
* @param abilities - Optional array of abilities the token should have
|
|
774
|
-
* @param options - Optional token configuration
|
|
775
|
-
*
|
|
776
|
-
* @example
|
|
777
|
-
* const token = await guard.createToken(user, ['read', 'write'], {
|
|
778
|
-
* name: 'Mobile App',
|
|
779
|
-
* expiresIn: '7d'
|
|
780
|
-
* })
|
|
781
|
-
* console.log('Token:', token.value.release())
|
|
782
|
-
*/
|
|
783
|
-
async createToken(user, abilities, options) {
|
|
784
|
-
return await this.#userProvider.createToken(user, abilities, options);
|
|
785
|
-
}
|
|
786
|
-
/**
|
|
787
|
-
* Invalidates the currently authenticated token (sign out)
|
|
788
|
-
*
|
|
789
|
-
* @example
|
|
790
|
-
* await guard.invalidateToken()
|
|
791
|
-
* console.log('Token invalidated successfully')
|
|
792
|
-
*/
|
|
793
|
-
async invalidateToken() {
|
|
794
|
-
const bearerToken = new Secret2(this.#getBearerToken());
|
|
795
|
-
return await this.#userProvider.invalidateToken(bearerToken);
|
|
796
|
-
}
|
|
797
|
-
/**
|
|
798
|
-
* Returns the Authorization header clients can use to authenticate
|
|
799
|
-
* the request.
|
|
800
|
-
*
|
|
801
|
-
* @param user - The user to authenticate as
|
|
802
|
-
* @param abilities - Optional array of abilities
|
|
803
|
-
* @param options - Optional token configuration
|
|
804
|
-
*
|
|
805
|
-
* @example
|
|
806
|
-
* const clientAuth = await guard.authenticateAsClient(user, ['read'])
|
|
807
|
-
* // Use clientAuth.headers.authorization in API tests
|
|
808
|
-
*/
|
|
809
|
-
async authenticateAsClient(user, abilities, options) {
|
|
810
|
-
const token = await this.#userProvider.createToken(user, abilities, options);
|
|
811
|
-
return {
|
|
812
|
-
headers: {
|
|
813
|
-
authorization: `Bearer ${token.value.release()}`
|
|
814
|
-
}
|
|
815
|
-
};
|
|
816
|
-
}
|
|
817
|
-
/**
|
|
818
|
-
* Silently check if the user is authenticated or not. The
|
|
819
|
-
* method is same as the "authenticate" method but does not
|
|
820
|
-
* throw any exceptions.
|
|
821
|
-
*
|
|
822
|
-
* @example
|
|
823
|
-
* const isAuthenticated = await guard.check()
|
|
824
|
-
* if (isAuthenticated) {
|
|
825
|
-
* const user = guard.user
|
|
826
|
-
* console.log('User is authenticated:', user.email)
|
|
827
|
-
* }
|
|
828
|
-
*/
|
|
829
|
-
async check() {
|
|
830
|
-
try {
|
|
831
|
-
await this.authenticate();
|
|
832
|
-
return true;
|
|
833
|
-
} catch (error) {
|
|
834
|
-
if (error instanceof E_UNAUTHORIZED_ACCESS) {
|
|
835
|
-
return false;
|
|
836
|
-
}
|
|
837
|
-
throw error;
|
|
838
|
-
}
|
|
839
|
-
}
|
|
390
|
+
#name;
|
|
391
|
+
#ctx;
|
|
392
|
+
#userProvider;
|
|
393
|
+
#emitter;
|
|
394
|
+
driverName = "access_tokens";
|
|
395
|
+
authenticationAttempted = false;
|
|
396
|
+
isAuthenticated = false;
|
|
397
|
+
user;
|
|
398
|
+
constructor(name, ctx, emitter, userProvider) {
|
|
399
|
+
this.#name = name;
|
|
400
|
+
this.#ctx = ctx;
|
|
401
|
+
this.#emitter = emitter;
|
|
402
|
+
this.#userProvider = userProvider;
|
|
403
|
+
}
|
|
404
|
+
#authenticationFailed() {
|
|
405
|
+
const error = new E_UNAUTHORIZED_ACCESS("Unauthorized access", { guardDriverName: this.driverName });
|
|
406
|
+
this.#emitter.emit("access_tokens_auth:authentication_failed", {
|
|
407
|
+
ctx: this.#ctx,
|
|
408
|
+
guardName: this.#name,
|
|
409
|
+
error
|
|
410
|
+
});
|
|
411
|
+
return error;
|
|
412
|
+
}
|
|
413
|
+
#getBearerToken() {
|
|
414
|
+
const [type, token] = this.#ctx.request.header("authorization", "").split(" ");
|
|
415
|
+
if (!type || type.toLowerCase() !== "bearer" || !token) throw this.#authenticationFailed();
|
|
416
|
+
return token;
|
|
417
|
+
}
|
|
418
|
+
getUserOrFail() {
|
|
419
|
+
if (!this.user) throw new E_UNAUTHORIZED_ACCESS("Unauthorized access", { guardDriverName: this.driverName });
|
|
420
|
+
return this.user;
|
|
421
|
+
}
|
|
422
|
+
async authenticate() {
|
|
423
|
+
if (this.authenticationAttempted) return this.getUserOrFail();
|
|
424
|
+
this.authenticationAttempted = true;
|
|
425
|
+
this.#emitter.emit("access_tokens_auth:authentication_attempted", {
|
|
426
|
+
ctx: this.#ctx,
|
|
427
|
+
guardName: this.#name
|
|
428
|
+
});
|
|
429
|
+
const bearerToken = new Secret(this.#getBearerToken());
|
|
430
|
+
const token = await this.#userProvider.verifyToken(bearerToken);
|
|
431
|
+
if (!token) throw this.#authenticationFailed();
|
|
432
|
+
const providerUser = await this.#userProvider.findById(token.tokenableId);
|
|
433
|
+
if (!providerUser) throw this.#authenticationFailed();
|
|
434
|
+
this.isAuthenticated = true;
|
|
435
|
+
this.user = providerUser.getOriginal();
|
|
436
|
+
this.user.currentAccessToken = token;
|
|
437
|
+
this.#emitter.emit("access_tokens_auth:authentication_succeeded", {
|
|
438
|
+
ctx: this.#ctx,
|
|
439
|
+
token,
|
|
440
|
+
guardName: this.#name,
|
|
441
|
+
user: this.user
|
|
442
|
+
});
|
|
443
|
+
return this.user;
|
|
444
|
+
}
|
|
445
|
+
async createToken(user, abilities, options) {
|
|
446
|
+
return await this.#userProvider.createToken(user, abilities, options);
|
|
447
|
+
}
|
|
448
|
+
async invalidateToken() {
|
|
449
|
+
const bearerToken = new Secret(this.#getBearerToken());
|
|
450
|
+
return await this.#userProvider.invalidateToken(bearerToken);
|
|
451
|
+
}
|
|
452
|
+
async authenticateAsClient(user, abilities, options) {
|
|
453
|
+
return { headers: { authorization: `Bearer ${(await this.#userProvider.createToken(user, abilities, options)).value.release()}` } };
|
|
454
|
+
}
|
|
455
|
+
async check() {
|
|
456
|
+
try {
|
|
457
|
+
await this.authenticate();
|
|
458
|
+
return true;
|
|
459
|
+
} catch (error) {
|
|
460
|
+
if (error instanceof E_UNAUTHORIZED_ACCESS) return false;
|
|
461
|
+
throw error;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
840
464
|
};
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
user.$primaryKeyValue,
|
|
985
|
-
this.tokenSecretLength,
|
|
986
|
-
options?.expiresIn || this.options.expiresIn
|
|
987
|
-
);
|
|
988
|
-
const dbRow = {
|
|
989
|
-
tokenable_id: transientToken.userId,
|
|
990
|
-
type: this.type,
|
|
991
|
-
name: options?.name || null,
|
|
992
|
-
hash: transientToken.hash,
|
|
993
|
-
abilities: JSON.stringify(abilities),
|
|
994
|
-
created_at: /* @__PURE__ */ new Date(),
|
|
995
|
-
updated_at: /* @__PURE__ */ new Date(),
|
|
996
|
-
last_used_at: null,
|
|
997
|
-
expires_at: transientToken.expiresAt || null
|
|
998
|
-
};
|
|
999
|
-
const result = await queryClient.table(this.table).insert(dbRow).returning("id");
|
|
1000
|
-
const id = this.#isObject(result[0]) ? result[0].id : result[0];
|
|
1001
|
-
if (!id) {
|
|
1002
|
-
throw new RuntimeException2(
|
|
1003
|
-
`Cannot save access token. The result "${inspect(result)}" of insert query is unexpected`
|
|
1004
|
-
);
|
|
1005
|
-
}
|
|
1006
|
-
return new AccessToken({
|
|
1007
|
-
identifier: id,
|
|
1008
|
-
tokenableId: dbRow.tokenable_id,
|
|
1009
|
-
type: dbRow.type,
|
|
1010
|
-
prefix: this.prefix,
|
|
1011
|
-
secret: transientToken.secret,
|
|
1012
|
-
name: dbRow.name,
|
|
1013
|
-
hash: dbRow.hash,
|
|
1014
|
-
abilities: JSON.parse(dbRow.abilities),
|
|
1015
|
-
createdAt: dbRow.created_at,
|
|
1016
|
-
updatedAt: dbRow.updated_at,
|
|
1017
|
-
lastUsedAt: dbRow.last_used_at,
|
|
1018
|
-
expiresAt: dbRow.expires_at
|
|
1019
|
-
});
|
|
1020
|
-
}
|
|
1021
|
-
/**
|
|
1022
|
-
* Find a token for a user by the token id
|
|
1023
|
-
*
|
|
1024
|
-
* @param user - The user instance that owns the token
|
|
1025
|
-
* @param identifier - The token identifier to search for
|
|
1026
|
-
*
|
|
1027
|
-
* @example
|
|
1028
|
-
* const token = await provider.find(user, 123)
|
|
1029
|
-
* if (token) {
|
|
1030
|
-
* console.log('Found token:', token.name)
|
|
1031
|
-
* }
|
|
1032
|
-
*/
|
|
1033
|
-
async find(user, identifier) {
|
|
1034
|
-
this.#ensureIsPersisted(user);
|
|
1035
|
-
const queryClient = await this.getDb();
|
|
1036
|
-
const dbRow = await queryClient.query().from(this.table).where({ id: identifier, tokenable_id: user.$primaryKeyValue, type: this.type }).limit(1).first();
|
|
1037
|
-
if (!dbRow) {
|
|
1038
|
-
return null;
|
|
1039
|
-
}
|
|
1040
|
-
return this.dbRowToAccessToken(dbRow);
|
|
1041
|
-
}
|
|
1042
|
-
/**
|
|
1043
|
-
* Delete a token by its id
|
|
1044
|
-
*
|
|
1045
|
-
* @param user - The user instance that owns the token
|
|
1046
|
-
* @param identifier - The token identifier to delete
|
|
1047
|
-
*
|
|
1048
|
-
* @example
|
|
1049
|
-
* const deletedCount = await provider.delete(user, 123)
|
|
1050
|
-
* console.log('Deleted tokens:', deletedCount)
|
|
1051
|
-
*/
|
|
1052
|
-
async delete(user, identifier) {
|
|
1053
|
-
this.#ensureIsPersisted(user);
|
|
1054
|
-
const queryClient = await this.getDb();
|
|
1055
|
-
const affectedRows = await queryClient.query().from(this.table).where({ id: identifier, tokenable_id: user.$primaryKeyValue, type: this.type }).del().exec();
|
|
1056
|
-
return affectedRows;
|
|
1057
|
-
}
|
|
1058
|
-
/**
|
|
1059
|
-
* Returns all the tokens for a given user
|
|
1060
|
-
*
|
|
1061
|
-
* @param user - The user instance to get tokens for
|
|
1062
|
-
*
|
|
1063
|
-
* @example
|
|
1064
|
-
* const tokens = await provider.all(user)
|
|
1065
|
-
* console.log('User has', tokens.length, 'tokens')
|
|
1066
|
-
* tokens.forEach(token => console.log(token.name))
|
|
1067
|
-
*/
|
|
1068
|
-
async all(user) {
|
|
1069
|
-
this.#ensureIsPersisted(user);
|
|
1070
|
-
const queryClient = await this.getDb();
|
|
1071
|
-
const dbRows = await queryClient.query().from(this.table).where({ tokenable_id: user.$primaryKeyValue, type: this.type }).ifDialect("postgres", (query) => {
|
|
1072
|
-
query.orderBy([
|
|
1073
|
-
{
|
|
1074
|
-
column: "last_used_at",
|
|
1075
|
-
order: "desc",
|
|
1076
|
-
nulls: "last"
|
|
1077
|
-
}
|
|
1078
|
-
]);
|
|
1079
|
-
}).unlessDialect("postgres", (query) => {
|
|
1080
|
-
query.orderBy([
|
|
1081
|
-
{
|
|
1082
|
-
column: "last_used_at",
|
|
1083
|
-
order: "asc",
|
|
1084
|
-
nulls: "last"
|
|
1085
|
-
}
|
|
1086
|
-
]);
|
|
1087
|
-
}).orderBy("id", "desc").exec();
|
|
1088
|
-
return dbRows.map((dbRow) => {
|
|
1089
|
-
return this.dbRowToAccessToken(dbRow);
|
|
1090
|
-
});
|
|
1091
|
-
}
|
|
1092
|
-
/**
|
|
1093
|
-
* Verifies a publicly shared access token and returns an
|
|
1094
|
-
* access token for it.
|
|
1095
|
-
*
|
|
1096
|
-
* Returns null when unable to verify the token or find it
|
|
1097
|
-
* inside the storage
|
|
1098
|
-
*
|
|
1099
|
-
* @param tokenValue - The token value to verify
|
|
1100
|
-
*
|
|
1101
|
-
* @example
|
|
1102
|
-
* const token = await provider.verify(new Secret('oat_abc123.def456'))
|
|
1103
|
-
* if (token && !token.isExpired()) {
|
|
1104
|
-
* console.log('Valid token for user:', token.tokenableId)
|
|
1105
|
-
* }
|
|
1106
|
-
*/
|
|
1107
|
-
async verify(tokenValue) {
|
|
1108
|
-
const decodedToken = AccessToken.decode(this.prefix, tokenValue.release());
|
|
1109
|
-
if (!decodedToken) {
|
|
1110
|
-
return null;
|
|
1111
|
-
}
|
|
1112
|
-
const db = await this.getDb();
|
|
1113
|
-
const dbRow = await db.query().from(this.table).where({ id: decodedToken.identifier, type: this.type }).limit(1).first();
|
|
1114
|
-
if (!dbRow) {
|
|
1115
|
-
return null;
|
|
1116
|
-
}
|
|
1117
|
-
dbRow.last_used_at = /* @__PURE__ */ new Date();
|
|
1118
|
-
await db.from(this.table).where({ id: dbRow.id, type: dbRow.type }).update({ last_used_at: dbRow.last_used_at });
|
|
1119
|
-
const accessToken = this.dbRowToAccessToken(dbRow);
|
|
1120
|
-
if (!accessToken.verify(decodedToken.secret) || accessToken.isExpired()) {
|
|
1121
|
-
return null;
|
|
1122
|
-
}
|
|
1123
|
-
return accessToken;
|
|
1124
|
-
}
|
|
1125
|
-
/**
|
|
1126
|
-
* Invalidates a token identified by its publicly shared token
|
|
1127
|
-
*
|
|
1128
|
-
* @param tokenValue - The token value to invalidate
|
|
1129
|
-
*
|
|
1130
|
-
* @example
|
|
1131
|
-
* const wasInvalidated = await provider.invalidate(new Secret('oat_abc123.def456'))
|
|
1132
|
-
* if (wasInvalidated) {
|
|
1133
|
-
* console.log('Token successfully invalidated')
|
|
1134
|
-
* }
|
|
1135
|
-
*/
|
|
1136
|
-
async invalidate(tokenValue) {
|
|
1137
|
-
const decodedToken = AccessToken.decode(this.prefix, tokenValue.release());
|
|
1138
|
-
if (!decodedToken) {
|
|
1139
|
-
return false;
|
|
1140
|
-
}
|
|
1141
|
-
const db = await this.getDb();
|
|
1142
|
-
const deleteCount = await db.query().from(this.table).where({ id: decodedToken.identifier, type: this.type }).del().exec();
|
|
1143
|
-
return Boolean(deleteCount);
|
|
1144
|
-
}
|
|
465
|
+
var DbAccessTokensProvider = class DbAccessTokensProvider {
|
|
466
|
+
static forModel(model, options) {
|
|
467
|
+
return new DbAccessTokensProvider({
|
|
468
|
+
tokenableModel: model,
|
|
469
|
+
...options || {}
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
type;
|
|
473
|
+
prefix;
|
|
474
|
+
table;
|
|
475
|
+
tokenSecretLength;
|
|
476
|
+
constructor(options) {
|
|
477
|
+
this.options = options;
|
|
478
|
+
this.table = options.table || "auth_access_tokens";
|
|
479
|
+
this.tokenSecretLength = options.tokenSecretLength || 40;
|
|
480
|
+
this.type = options.type || "auth_token";
|
|
481
|
+
this.prefix = options.prefix || "oat_";
|
|
482
|
+
}
|
|
483
|
+
#isObject(value) {
|
|
484
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
485
|
+
}
|
|
486
|
+
#ensureIsPersisted(user) {
|
|
487
|
+
const model = this.options.tokenableModel;
|
|
488
|
+
if (user instanceof model === false) throw new RuntimeException(`Invalid user object. It must be an instance of the "${model.name}" model`);
|
|
489
|
+
if (!user.$primaryKeyValue) throw new RuntimeException(`Cannot use "${model.name}" model for managing access tokens. The value of column "${model.primaryKey}" is undefined or null`);
|
|
490
|
+
}
|
|
491
|
+
dbRowToAccessToken(dbRow) {
|
|
492
|
+
return new AccessToken({
|
|
493
|
+
identifier: dbRow.id,
|
|
494
|
+
tokenableId: dbRow.tokenable_id,
|
|
495
|
+
type: dbRow.type,
|
|
496
|
+
name: dbRow.name,
|
|
497
|
+
hash: dbRow.hash,
|
|
498
|
+
abilities: JSON.parse(dbRow.abilities),
|
|
499
|
+
createdAt: typeof dbRow.created_at === "number" ? new Date(dbRow.created_at) : dbRow.created_at,
|
|
500
|
+
updatedAt: typeof dbRow.updated_at === "number" ? new Date(dbRow.updated_at) : dbRow.updated_at,
|
|
501
|
+
lastUsedAt: typeof dbRow.last_used_at === "number" ? new Date(dbRow.last_used_at) : dbRow.last_used_at,
|
|
502
|
+
expiresAt: typeof dbRow.expires_at === "number" ? new Date(dbRow.expires_at) : dbRow.expires_at
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
async getDb() {
|
|
506
|
+
const model = this.options.tokenableModel;
|
|
507
|
+
return model.$adapter.query(model).client;
|
|
508
|
+
}
|
|
509
|
+
async create(user, abilities = ["*"], options) {
|
|
510
|
+
this.#ensureIsPersisted(user);
|
|
511
|
+
const queryClient = await this.getDb();
|
|
512
|
+
const transientToken = AccessToken.createTransientToken(user.$primaryKeyValue, this.tokenSecretLength, options?.expiresIn || this.options.expiresIn);
|
|
513
|
+
const dbRow = {
|
|
514
|
+
tokenable_id: transientToken.userId,
|
|
515
|
+
type: this.type,
|
|
516
|
+
name: options?.name || null,
|
|
517
|
+
hash: transientToken.hash,
|
|
518
|
+
abilities: JSON.stringify(abilities),
|
|
519
|
+
created_at: /* @__PURE__ */ new Date(),
|
|
520
|
+
updated_at: /* @__PURE__ */ new Date(),
|
|
521
|
+
last_used_at: null,
|
|
522
|
+
expires_at: transientToken.expiresAt || null
|
|
523
|
+
};
|
|
524
|
+
const result = await queryClient.table(this.table).insert(dbRow).returning("id");
|
|
525
|
+
const id = this.#isObject(result[0]) ? result[0].id : result[0];
|
|
526
|
+
if (!id) throw new RuntimeException(`Cannot save access token. The result "${inspect(result)}" of insert query is unexpected`);
|
|
527
|
+
return new AccessToken({
|
|
528
|
+
identifier: id,
|
|
529
|
+
tokenableId: dbRow.tokenable_id,
|
|
530
|
+
type: dbRow.type,
|
|
531
|
+
prefix: this.prefix,
|
|
532
|
+
secret: transientToken.secret,
|
|
533
|
+
name: dbRow.name,
|
|
534
|
+
hash: dbRow.hash,
|
|
535
|
+
abilities: JSON.parse(dbRow.abilities),
|
|
536
|
+
createdAt: dbRow.created_at,
|
|
537
|
+
updatedAt: dbRow.updated_at,
|
|
538
|
+
lastUsedAt: dbRow.last_used_at,
|
|
539
|
+
expiresAt: dbRow.expires_at
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
async find(user, identifier) {
|
|
543
|
+
this.#ensureIsPersisted(user);
|
|
544
|
+
const dbRow = await (await this.getDb()).query().from(this.table).where({
|
|
545
|
+
id: identifier,
|
|
546
|
+
tokenable_id: user.$primaryKeyValue,
|
|
547
|
+
type: this.type
|
|
548
|
+
}).limit(1).first();
|
|
549
|
+
if (!dbRow) return null;
|
|
550
|
+
return this.dbRowToAccessToken(dbRow);
|
|
551
|
+
}
|
|
552
|
+
async delete(user, identifier) {
|
|
553
|
+
this.#ensureIsPersisted(user);
|
|
554
|
+
return await (await this.getDb()).query().from(this.table).where({
|
|
555
|
+
id: identifier,
|
|
556
|
+
tokenable_id: user.$primaryKeyValue,
|
|
557
|
+
type: this.type
|
|
558
|
+
}).del().exec();
|
|
559
|
+
}
|
|
560
|
+
async all(user) {
|
|
561
|
+
this.#ensureIsPersisted(user);
|
|
562
|
+
return (await (await this.getDb()).query().from(this.table).where({
|
|
563
|
+
tokenable_id: user.$primaryKeyValue,
|
|
564
|
+
type: this.type
|
|
565
|
+
}).ifDialect("postgres", (query) => {
|
|
566
|
+
query.orderBy([{
|
|
567
|
+
column: "last_used_at",
|
|
568
|
+
order: "desc",
|
|
569
|
+
nulls: "last"
|
|
570
|
+
}]);
|
|
571
|
+
}).unlessDialect("postgres", (query) => {
|
|
572
|
+
query.orderBy([{
|
|
573
|
+
column: "last_used_at",
|
|
574
|
+
order: "asc",
|
|
575
|
+
nulls: "last"
|
|
576
|
+
}]);
|
|
577
|
+
}).orderBy("id", "desc").exec()).map((dbRow) => {
|
|
578
|
+
return this.dbRowToAccessToken(dbRow);
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
async verify(tokenValue) {
|
|
582
|
+
const decodedToken = AccessToken.decode(this.prefix, tokenValue.release());
|
|
583
|
+
if (!decodedToken) return null;
|
|
584
|
+
const db = await this.getDb();
|
|
585
|
+
const dbRow = await db.query().from(this.table).where({
|
|
586
|
+
id: decodedToken.identifier,
|
|
587
|
+
type: this.type
|
|
588
|
+
}).limit(1).first();
|
|
589
|
+
if (!dbRow) return null;
|
|
590
|
+
dbRow.last_used_at = /* @__PURE__ */ new Date();
|
|
591
|
+
await db.from(this.table).where({
|
|
592
|
+
id: dbRow.id,
|
|
593
|
+
type: dbRow.type
|
|
594
|
+
}).update({ last_used_at: dbRow.last_used_at });
|
|
595
|
+
const accessToken = this.dbRowToAccessToken(dbRow);
|
|
596
|
+
if (!accessToken.verify(decodedToken.secret) || accessToken.isExpired()) return null;
|
|
597
|
+
return accessToken;
|
|
598
|
+
}
|
|
599
|
+
async invalidate(tokenValue) {
|
|
600
|
+
const decodedToken = AccessToken.decode(this.prefix, tokenValue.release());
|
|
601
|
+
if (!decodedToken) return false;
|
|
602
|
+
const deleteCount = await (await this.getDb()).query().from(this.table).where({
|
|
603
|
+
id: decodedToken.identifier,
|
|
604
|
+
type: this.type
|
|
605
|
+
}).del().exec();
|
|
606
|
+
return Boolean(deleteCount);
|
|
607
|
+
}
|
|
1145
608
|
};
|
|
1146
|
-
|
|
1147
|
-
// modules/access_tokens_guard/user_providers/lucid.ts
|
|
1148
|
-
import { RuntimeException as RuntimeException3 } from "@adonisjs/core/exceptions";
|
|
1149
609
|
var AccessTokensLucidUserProvider = class {
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
async getTokensProvider() {
|
|
1192
|
-
const model = await this.getModel();
|
|
1193
|
-
if (!model[this.options.tokens]) {
|
|
1194
|
-
throw new RuntimeException3(
|
|
1195
|
-
`Cannot use "${model.name}" model for verifying access tokens. Make sure to assign a token provider to the model.`
|
|
1196
|
-
);
|
|
1197
|
-
}
|
|
1198
|
-
return model[this.options.tokens];
|
|
1199
|
-
}
|
|
1200
|
-
/**
|
|
1201
|
-
* Creates an adapter user for the guard
|
|
1202
|
-
*
|
|
1203
|
-
* @param user - The user model instance
|
|
1204
|
-
*
|
|
1205
|
-
* @example
|
|
1206
|
-
* const guardUser = await provider.createUserForGuard(user)
|
|
1207
|
-
* console.log('User ID:', guardUser.getId())
|
|
1208
|
-
* console.log('Original user:', guardUser.getOriginal())
|
|
1209
|
-
*/
|
|
1210
|
-
async createUserForGuard(user) {
|
|
1211
|
-
const model = await this.getModel();
|
|
1212
|
-
if (user instanceof model === false) {
|
|
1213
|
-
throw new RuntimeException3(
|
|
1214
|
-
`Invalid user object. It must be an instance of the "${model.name}" model`
|
|
1215
|
-
);
|
|
1216
|
-
}
|
|
1217
|
-
return {
|
|
1218
|
-
getId() {
|
|
1219
|
-
if (!user.$primaryKeyValue) {
|
|
1220
|
-
throw new RuntimeException3(
|
|
1221
|
-
`Cannot use "${model.name}" model for authentication. The value of column "${model.primaryKey}" is undefined or null`
|
|
1222
|
-
);
|
|
1223
|
-
}
|
|
1224
|
-
return user.$primaryKeyValue;
|
|
1225
|
-
},
|
|
1226
|
-
getOriginal() {
|
|
1227
|
-
return user;
|
|
1228
|
-
}
|
|
1229
|
-
};
|
|
1230
|
-
}
|
|
1231
|
-
/**
|
|
1232
|
-
* Create a token for a given user
|
|
1233
|
-
*
|
|
1234
|
-
* @param user - The user to create a token for
|
|
1235
|
-
* @param abilities - Optional array of abilities the token should have
|
|
1236
|
-
* @param options - Optional token configuration
|
|
1237
|
-
*
|
|
1238
|
-
* @example
|
|
1239
|
-
* const token = await provider.createToken(user, ['read', 'write'], {
|
|
1240
|
-
* name: 'API Token',
|
|
1241
|
-
* expiresIn: '30d'
|
|
1242
|
-
* })
|
|
1243
|
-
* console.log('Created token:', token.value.release())
|
|
1244
|
-
*/
|
|
1245
|
-
async createToken(user, abilities, options) {
|
|
1246
|
-
const tokensProvider = await this.getTokensProvider();
|
|
1247
|
-
return tokensProvider.create(user, abilities, options);
|
|
1248
|
-
}
|
|
1249
|
-
/**
|
|
1250
|
-
* Invalidates a token identified by its publicly shared token
|
|
1251
|
-
*
|
|
1252
|
-
* @param tokenValue - The token value to invalidate
|
|
1253
|
-
*
|
|
1254
|
-
* @example
|
|
1255
|
-
* const wasInvalidated = await provider.invalidateToken(
|
|
1256
|
-
* new Secret('oat_abc123.def456')
|
|
1257
|
-
* )
|
|
1258
|
-
* console.log('Token invalidated:', wasInvalidated)
|
|
1259
|
-
*/
|
|
1260
|
-
async invalidateToken(tokenValue) {
|
|
1261
|
-
const tokensProvider = await this.getTokensProvider();
|
|
1262
|
-
return tokensProvider.invalidate(tokenValue);
|
|
1263
|
-
}
|
|
1264
|
-
/**
|
|
1265
|
-
* Finds a user by the user id
|
|
1266
|
-
*
|
|
1267
|
-
* @param identifier - The user identifier to search for
|
|
1268
|
-
*
|
|
1269
|
-
* @example
|
|
1270
|
-
* const guardUser = await provider.findById(123)
|
|
1271
|
-
* if (guardUser) {
|
|
1272
|
-
* const originalUser = guardUser.getOriginal()
|
|
1273
|
-
* console.log('Found user:', originalUser.email)
|
|
1274
|
-
* }
|
|
1275
|
-
*/
|
|
1276
|
-
async findById(identifier) {
|
|
1277
|
-
const model = await this.getModel();
|
|
1278
|
-
const user = await model.find(identifier);
|
|
1279
|
-
if (!user) {
|
|
1280
|
-
return null;
|
|
1281
|
-
}
|
|
1282
|
-
return this.createUserForGuard(user);
|
|
1283
|
-
}
|
|
1284
|
-
/**
|
|
1285
|
-
* Verifies a publicly shared access token and returns an
|
|
1286
|
-
* access token for it.
|
|
1287
|
-
*
|
|
1288
|
-
* @param tokenValue - The token value to verify
|
|
1289
|
-
*
|
|
1290
|
-
* @example
|
|
1291
|
-
* const token = await provider.verifyToken(
|
|
1292
|
-
* new Secret('oat_abc123.def456')
|
|
1293
|
-
* )
|
|
1294
|
-
* if (token && !token.isExpired()) {
|
|
1295
|
-
* console.log('Valid token with abilities:', token.abilities)
|
|
1296
|
-
* }
|
|
1297
|
-
*/
|
|
1298
|
-
async verifyToken(tokenValue) {
|
|
1299
|
-
const tokensProvider = await this.getTokensProvider();
|
|
1300
|
-
return tokensProvider.verify(tokenValue);
|
|
1301
|
-
}
|
|
610
|
+
model;
|
|
611
|
+
constructor(options) {
|
|
612
|
+
this.options = options;
|
|
613
|
+
}
|
|
614
|
+
async getModel() {
|
|
615
|
+
if (this.model && !("hot" in import.meta)) return this.model;
|
|
616
|
+
this.model = (await this.options.model()).default;
|
|
617
|
+
return this.model;
|
|
618
|
+
}
|
|
619
|
+
async getTokensProvider() {
|
|
620
|
+
const model = await this.getModel();
|
|
621
|
+
if (!model[this.options.tokens]) throw new RuntimeException(`Cannot use "${model.name}" model for verifying access tokens. Make sure to assign a token provider to the model.`);
|
|
622
|
+
return model[this.options.tokens];
|
|
623
|
+
}
|
|
624
|
+
async createUserForGuard(user) {
|
|
625
|
+
const model = await this.getModel();
|
|
626
|
+
if (user instanceof model === false) throw new RuntimeException(`Invalid user object. It must be an instance of the "${model.name}" model`);
|
|
627
|
+
return {
|
|
628
|
+
getId() {
|
|
629
|
+
if (!user.$primaryKeyValue) throw new RuntimeException(`Cannot use "${model.name}" model for authentication. The value of column "${model.primaryKey}" is undefined or null`);
|
|
630
|
+
return user.$primaryKeyValue;
|
|
631
|
+
},
|
|
632
|
+
getOriginal() {
|
|
633
|
+
return user;
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
async createToken(user, abilities, options) {
|
|
638
|
+
return (await this.getTokensProvider()).create(user, abilities, options);
|
|
639
|
+
}
|
|
640
|
+
async invalidateToken(tokenValue) {
|
|
641
|
+
return (await this.getTokensProvider()).invalidate(tokenValue);
|
|
642
|
+
}
|
|
643
|
+
async findById(identifier) {
|
|
644
|
+
const user = await (await this.getModel()).find(identifier);
|
|
645
|
+
if (!user) return null;
|
|
646
|
+
return this.createUserForGuard(user);
|
|
647
|
+
}
|
|
648
|
+
async verifyToken(tokenValue) {
|
|
649
|
+
return (await this.getTokensProvider()).verify(tokenValue);
|
|
650
|
+
}
|
|
1302
651
|
};
|
|
1303
|
-
|
|
1304
|
-
// modules/access_tokens_guard/define_config.ts
|
|
1305
652
|
function tokensGuard(config) {
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
}
|
|
1312
|
-
};
|
|
653
|
+
return { async resolver(name, app) {
|
|
654
|
+
const emitter = await app.container.make("emitter");
|
|
655
|
+
const provider = "resolver" in config.provider ? await config.provider.resolver(app) : config.provider;
|
|
656
|
+
return (ctx) => new AccessTokensGuard(name, ctx, emitter, provider);
|
|
657
|
+
} };
|
|
1313
658
|
}
|
|
1314
659
|
function tokensUserProvider(config) {
|
|
1315
|
-
|
|
660
|
+
return new AccessTokensLucidUserProvider(config);
|
|
1316
661
|
}
|
|
1317
|
-
export {
|
|
1318
|
-
AccessToken,
|
|
1319
|
-
AccessTokensGuard,
|
|
1320
|
-
AccessTokensLucidUserProvider,
|
|
1321
|
-
DbAccessTokensProvider,
|
|
1322
|
-
tokensGuard,
|
|
1323
|
-
tokensUserProvider
|
|
1324
|
-
};
|
|
662
|
+
export { AccessToken, AccessTokensGuard, AccessTokensLucidUserProvider, DbAccessTokensProvider, tokensGuard, tokensUserProvider };
|