@maximemrf/adonisjs-jwt 1.0.0-rc.6 → 1.0.0-rc.7
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.
|
@@ -43,6 +43,7 @@ export function jwtGuard(config) {
|
|
|
43
43
|
* the first request, when the app would already be serving traffic.
|
|
44
44
|
*/
|
|
45
45
|
validateLifetimes(options, PREFIX);
|
|
46
|
+
validateSigningMethod(options, PREFIX, { usesAppKey });
|
|
46
47
|
let driver;
|
|
47
48
|
if (usesAppKey) {
|
|
48
49
|
/**
|
|
@@ -53,7 +54,6 @@ export function jwtGuard(config) {
|
|
|
53
54
|
assertAppKey(process.env.APP_KEY);
|
|
54
55
|
}
|
|
55
56
|
else {
|
|
56
|
-
validateSigningMethod(options, PREFIX);
|
|
57
57
|
driver = resolveDriver(options, PREFIX);
|
|
58
58
|
}
|
|
59
59
|
return {
|
package/build/src/guard.js
CHANGED
|
@@ -107,6 +107,7 @@ export class JwtGuard {
|
|
|
107
107
|
}
|
|
108
108
|
const providerUser = await this.#userProvider.createUserForGuard(user);
|
|
109
109
|
const signPayload = this.#options.content(providerUser);
|
|
110
|
+
assertNoGuardClaims(signPayload, this.#options);
|
|
110
111
|
const token = this.#signAccessToken(signPayload);
|
|
111
112
|
let refreshToken;
|
|
112
113
|
if (this.#refreshTokenUserProvider) {
|
|
@@ -407,6 +408,23 @@ export class JwtGuard {
|
|
|
407
408
|
}
|
|
408
409
|
}
|
|
409
410
|
const REFRESH_TOKENS_NOT_CONFIGURED = 'JWT guard refresh tokens are not configured: set `refreshTokenUserProvider` in the guard config';
|
|
411
|
+
/**
|
|
412
|
+
* The guard sets `exp`, and `iss` / `aud` when `issuer` / `audience` are
|
|
413
|
+
* configured. jsonwebtoken refuses a payload that sets them too, with a
|
|
414
|
+
* message about its own options (`options.expiresIn`) that the app never set.
|
|
415
|
+
*/
|
|
416
|
+
function assertNoGuardClaims(payload, options) {
|
|
417
|
+
const conflicts = [['exp', 'tokenExpiresIn']];
|
|
418
|
+
if (options.issuer)
|
|
419
|
+
conflicts.push(['iss', 'issuer']);
|
|
420
|
+
if (options.audience)
|
|
421
|
+
conflicts.push(['aud', 'audience']);
|
|
422
|
+
for (const [claim, option] of conflicts) {
|
|
423
|
+
if (payload[claim] !== undefined) {
|
|
424
|
+
throw new RuntimeException(`JWT guard \`content\` must not set \`${claim}\`: the guard sets it from \`${option}\``);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
410
428
|
function isUserId(value) {
|
|
411
429
|
return ((typeof value === 'string' && value !== '') ||
|
|
412
430
|
(typeof value === 'number' && Number.isFinite(value)) ||
|
package/build/src/types.d.ts
CHANGED
|
@@ -135,6 +135,13 @@ type JwtSharedOptions = {
|
|
|
135
135
|
*/
|
|
136
136
|
verifyPayload?: JwtVerifyPayload;
|
|
137
137
|
};
|
|
138
|
+
/**
|
|
139
|
+
* Claims set by the guard: `exp` comes from `tokenExpiresIn`, so `content`
|
|
140
|
+
* must not set it
|
|
141
|
+
*/
|
|
142
|
+
type GuardClaims = {
|
|
143
|
+
exp?: never;
|
|
144
|
+
};
|
|
138
145
|
/**
|
|
139
146
|
* `content` builds the payload of the access tokens. Without `getUserId`,
|
|
140
147
|
* the guard reads the user id from the `userId` claim, so `content` must
|
|
@@ -146,14 +153,14 @@ export type JwtContentOptions<RealUser> = {
|
|
|
146
153
|
* Defaults to `payload.userId`. Use e.g. `(payload) => payload.sub` for external providers.
|
|
147
154
|
*/
|
|
148
155
|
getUserId?: undefined;
|
|
149
|
-
content?: (user: JwtGuardUser<RealUser>) => Record<string, any> & BaseJwtContent;
|
|
156
|
+
content?: (user: JwtGuardUser<RealUser>) => Record<string, any> & BaseJwtContent & GuardClaims;
|
|
150
157
|
} | {
|
|
151
158
|
/**
|
|
152
159
|
* Extract the user id from a verified token payload.
|
|
153
160
|
* Defaults to `payload.userId`. Use e.g. `(payload) => payload.sub` for external providers.
|
|
154
161
|
*/
|
|
155
162
|
getUserId: JwtGetUserId;
|
|
156
|
-
content?: (user: JwtGuardUser<RealUser>) => Record<string, any
|
|
163
|
+
content?: (user: JwtGuardUser<RealUser>) => Record<string, any> & GuardClaims;
|
|
157
164
|
};
|
|
158
165
|
/**
|
|
159
166
|
* Options of the `JwtGuard` constructor
|
|
@@ -10,7 +10,9 @@ export declare function validateLifetimes(options: Pick<JwtGuardOptions, 'tokenE
|
|
|
10
10
|
/**
|
|
11
11
|
* Exactly one signing method: a secret, an asymmetric key pair, or a JWKS endpoint
|
|
12
12
|
*/
|
|
13
|
-
export declare function validateSigningMethod(options: ReleasedSecrets<JwtGuardOptions>, prefix: string
|
|
13
|
+
export declare function validateSigningMethod(options: ReleasedSecrets<JwtGuardOptions>, prefix: string, { usesAppKey }?: {
|
|
14
|
+
usesAppKey?: boolean;
|
|
15
|
+
}): void;
|
|
14
16
|
/**
|
|
15
17
|
* Accept `Secret` values (`Env.schema.secret()` in AdonisJS v7) for the
|
|
16
18
|
* signing keys, and work with their string value
|
package/build/src/validation.js
CHANGED
|
@@ -44,7 +44,7 @@ function assertDuration(value, name, prefix) {
|
|
|
44
44
|
/**
|
|
45
45
|
* Exactly one signing method: a secret, an asymmetric key pair, or a JWKS endpoint
|
|
46
46
|
*/
|
|
47
|
-
export function validateSigningMethod(options, prefix) {
|
|
47
|
+
export function validateSigningMethod(options, prefix, { usesAppKey = false } = {}) {
|
|
48
48
|
const asymmetricPartial = options.privateKey !== undefined ||
|
|
49
49
|
options.publicKey !== undefined ||
|
|
50
50
|
options.algorithm !== undefined;
|
|
@@ -89,7 +89,11 @@ export function validateSigningMethod(options, prefix) {
|
|
|
89
89
|
!(typeof options.jwks.jwksUri === 'string' && options.jwks.jwksUri.trim() !== '')) {
|
|
90
90
|
throw new Error(`${prefix} \`jwks.jwksUri\` is required to fetch the identity provider keys`);
|
|
91
91
|
}
|
|
92
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Without a signing method, `jwtGuard()` derives the secret from the app
|
|
94
|
+
* key in the resolver
|
|
95
|
+
*/
|
|
96
|
+
if (!usesAppKey && !options.jwks && !usesAsymmetric && !options.secret) {
|
|
93
97
|
throw new Error(`${prefix} requires \`secret\` (symmetric), or \`privateKey\` + \`publicKey\` + \`algorithm\` (asymmetric), or \`jwks\``);
|
|
94
98
|
}
|
|
95
99
|
}
|