@maximemrf/adonisjs-jwt 0.7.0-alpha.0 → 0.7.0-alpha.2
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/README.md +17 -9
- package/build/src/define_config.d.ts +2 -0
- package/build/src/define_config.js +3 -0
- package/build/src/jwks.d.ts +7 -0
- package/build/src/jwks.js +14 -0
- package/build/src/jwt.js +16 -2
- package/build/src/types.d.ts +4 -0
- package/package.json +14 -13
package/README.md
CHANGED
|
@@ -131,7 +131,13 @@ export default class extends BaseSchema {
|
|
|
131
131
|
async up() {
|
|
132
132
|
this.schema.createTable(this.tableName, (table) => {
|
|
133
133
|
table.increments()
|
|
134
|
-
table
|
|
134
|
+
table
|
|
135
|
+
.integer('tokenable_id')
|
|
136
|
+
.notNullable()
|
|
137
|
+
.unsigned()
|
|
138
|
+
.references('id')
|
|
139
|
+
.inTable('users')
|
|
140
|
+
.onDelete('CASCADE')
|
|
135
141
|
table.string('type').notNullable()
|
|
136
142
|
table.string('name').nullable()
|
|
137
143
|
table.string('hash', 80).notNullable()
|
|
@@ -193,16 +199,18 @@ router.post('login', async ({ request, auth }) => {
|
|
|
193
199
|
})
|
|
194
200
|
|
|
195
201
|
// if the jwt guard is the default guard
|
|
196
|
-
router
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
202
|
+
router
|
|
203
|
+
.get('/', async ({ auth }) => {
|
|
204
|
+
return auth.getUserOrFail()
|
|
205
|
+
})
|
|
206
|
+
.use(middleware.auth())
|
|
200
207
|
|
|
201
208
|
// if the jwt guard is not the default guard
|
|
202
|
-
router
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
209
|
+
router
|
|
210
|
+
.get('/', async ({ auth }) => {
|
|
211
|
+
return auth.use('jwt').getUserOrFail()
|
|
212
|
+
})
|
|
213
|
+
.use(middleware.auth({ guards: ['jwt'] }))
|
|
206
214
|
|
|
207
215
|
// if you use the refresh token
|
|
208
216
|
router.post('jwt/refresh', async ({ auth }) => {
|
|
@@ -4,6 +4,7 @@ import { JwtGuardUser, JwtUserProviderContract } from './types.js';
|
|
|
4
4
|
import { JwtGuard } from './jwt.js';
|
|
5
5
|
import type { StringValue } from 'ms';
|
|
6
6
|
import { AccessTokensUserProviderContract } from '@adonisjs/auth/types/access_tokens';
|
|
7
|
+
import { Options } from 'jwks-rsa';
|
|
7
8
|
export declare function jwtGuard<UserProvider extends JwtUserProviderContract<unknown>>(config: {
|
|
8
9
|
provider: UserProvider;
|
|
9
10
|
refreshTokenUserProvider?: AccessTokensUserProviderContract<unknown>;
|
|
@@ -15,4 +16,5 @@ export declare function jwtGuard<UserProvider extends JwtUserProviderContract<un
|
|
|
15
16
|
refreshTokenAbilities?: string[];
|
|
16
17
|
secret?: string;
|
|
17
18
|
content: <T>(user: JwtGuardUser<T>) => Record<string | number, any>;
|
|
19
|
+
jwks?: Options;
|
|
18
20
|
}): GuardConfigProvider<(ctx: HttpContext) => JwtGuard<UserProvider>>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { JwtGuard } from './jwt.js';
|
|
2
|
+
import { JwksManager } from './jwks.js';
|
|
2
3
|
export function jwtGuard(config) {
|
|
3
4
|
return {
|
|
4
5
|
async resolver(_, app) {
|
|
@@ -13,6 +14,8 @@ export function jwtGuard(config) {
|
|
|
13
14
|
useCookiesForRefreshToken: config.useCookiesForRefreshToken,
|
|
14
15
|
refreshTokenAbilities: config.refreshTokenAbilities,
|
|
15
16
|
content: config.content,
|
|
17
|
+
jwks: config.jwks,
|
|
18
|
+
jwksClient: config.jwks ? new JwksManager(config.jwks).getClient() : undefined,
|
|
16
19
|
};
|
|
17
20
|
return (ctx) => new JwtGuard(ctx, config.provider, options);
|
|
18
21
|
},
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { JwksClient } from 'jwks-rsa';
|
|
2
|
+
export class JwksManager {
|
|
3
|
+
client;
|
|
4
|
+
constructor(options) {
|
|
5
|
+
this.client = new JwksClient(options);
|
|
6
|
+
}
|
|
7
|
+
getClient() {
|
|
8
|
+
return this.client;
|
|
9
|
+
}
|
|
10
|
+
async getSigningKey(kid) {
|
|
11
|
+
const key = await this.client.getSigningKey(kid);
|
|
12
|
+
return key.getPublicKey();
|
|
13
|
+
}
|
|
14
|
+
}
|
package/build/src/jwt.js
CHANGED
|
@@ -8,6 +8,7 @@ export class JwtGuard {
|
|
|
8
8
|
#options;
|
|
9
9
|
#tokenName;
|
|
10
10
|
#refreshTokenName = 'refreshToken';
|
|
11
|
+
#jwksManager;
|
|
11
12
|
constructor(ctx, userProvider, option) {
|
|
12
13
|
this.#ctx = ctx;
|
|
13
14
|
this.#userProvider = userProvider;
|
|
@@ -16,6 +17,7 @@ export class JwtGuard {
|
|
|
16
17
|
if (!this.#options.content)
|
|
17
18
|
this.#options.content = (user) => ({ userId: user.getId() });
|
|
18
19
|
this.#tokenName = this.#options.tokenName ?? 'token';
|
|
20
|
+
this.#jwksManager = this.#options.jwksManager;
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
21
23
|
* A unique name for the guard driver
|
|
@@ -126,14 +128,26 @@ export class JwtGuard {
|
|
|
126
128
|
*/
|
|
127
129
|
let payload;
|
|
128
130
|
try {
|
|
129
|
-
|
|
131
|
+
if (this.#jwksManager) {
|
|
132
|
+
const decoded = jwt.decode(token, { complete: true });
|
|
133
|
+
if (!decoded || !decoded.header || !decoded.header.kid) {
|
|
134
|
+
throw new errors.E_UNAUTHORIZED_ACCESS('Unauthorized access', {
|
|
135
|
+
guardDriverName: this.driverName,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
const key = await this.#jwksManager.getSigningKey(decoded.header.kid);
|
|
139
|
+
payload = jwt.verify(token, key);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
payload = jwt.verify(token, this.#options.secret);
|
|
143
|
+
}
|
|
130
144
|
}
|
|
131
145
|
catch (error) {
|
|
132
146
|
throw new errors.E_UNAUTHORIZED_ACCESS('Unauthorized access', {
|
|
133
147
|
guardDriverName: this.driverName,
|
|
134
148
|
});
|
|
135
149
|
}
|
|
136
|
-
if (typeof payload !== 'object' || !('userId' in payload)) {
|
|
150
|
+
if (!payload || typeof payload !== 'object' || !('userId' in payload)) {
|
|
137
151
|
throw new errors.E_UNAUTHORIZED_ACCESS('Unauthorized access', {
|
|
138
152
|
guardDriverName: this.driverName,
|
|
139
153
|
});
|
package/build/src/types.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { symbols } from '@adonisjs/auth';
|
|
2
2
|
import type { StringValue } from 'ms';
|
|
3
3
|
import { AccessTokensUserProviderContract } from '@adonisjs/auth/types/access_tokens';
|
|
4
|
+
import { Options } from 'jwks-rsa';
|
|
5
|
+
import { JwksManager } from './jwks.js';
|
|
4
6
|
/**
|
|
5
7
|
* The bridge between the User provider and the
|
|
6
8
|
* Guard
|
|
@@ -40,6 +42,8 @@ export type BaseJwtContent = {
|
|
|
40
42
|
};
|
|
41
43
|
export type JwtGuardOptions<RealUser extends any = unknown> = {
|
|
42
44
|
secret: string;
|
|
45
|
+
jwks?: Options;
|
|
46
|
+
jwksManager?: JwksManager;
|
|
43
47
|
refreshTokenUserProvider?: AccessTokensUserProviderContract<RealUser>;
|
|
44
48
|
tokenName?: string;
|
|
45
49
|
expiresIn?: number | StringValue;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maximemrf/adonisjs-jwt",
|
|
3
3
|
"description": "Adonisjs v6 package for authentication with jwt token",
|
|
4
|
-
"version": "0.7.0-alpha.
|
|
4
|
+
"version": "0.7.0-alpha.2",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.6.0"
|
|
7
7
|
},
|
|
@@ -35,24 +35,24 @@
|
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@adonisjs/assembler": "^7.8.2",
|
|
38
|
-
"@adonisjs/auth": "^9.5.
|
|
39
|
-
"@adonisjs/core": "^6.19.
|
|
38
|
+
"@adonisjs/auth": "^9.5.1",
|
|
39
|
+
"@adonisjs/core": "^6.19.3",
|
|
40
40
|
"@adonisjs/eslint-config": "^2.1.2",
|
|
41
|
-
"@adonisjs/lucid": "^21.8.
|
|
41
|
+
"@adonisjs/lucid": "^21.8.2",
|
|
42
42
|
"@adonisjs/prettier-config": "^1.4.5",
|
|
43
43
|
"@adonisjs/tsconfig": "^1.4.1",
|
|
44
|
-
"@japa/assert": "^4.
|
|
45
|
-
"@japa/file-system": "^
|
|
46
|
-
"@japa/runner": "^
|
|
47
|
-
"@swc/core": "^1.
|
|
44
|
+
"@japa/assert": "^4.2.0",
|
|
45
|
+
"@japa/file-system": "^3.0.0",
|
|
46
|
+
"@japa/runner": "^5.3.0",
|
|
47
|
+
"@swc/core": "^1.15.8",
|
|
48
48
|
"@types/node": "^22.15.18",
|
|
49
49
|
"c8": "^10.1.3",
|
|
50
50
|
"copyfiles": "^2.4.1",
|
|
51
51
|
"del-cli": "^7.0.0",
|
|
52
|
-
"eslint": "^9.
|
|
52
|
+
"eslint": "^9.39.2",
|
|
53
53
|
"luxon": "^3.7.2",
|
|
54
|
-
"np": "^10.
|
|
55
|
-
"prettier": "^3.
|
|
54
|
+
"np": "^10.3.0",
|
|
55
|
+
"prettier": "^3.8.0",
|
|
56
56
|
"sqlite3": "^5.1.7",
|
|
57
57
|
"timekeeper": "^2.3.1",
|
|
58
58
|
"ts-node-maintained": "^10.9.6",
|
|
@@ -60,7 +60,8 @@
|
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@types/jsonwebtoken": "^9.0.10",
|
|
63
|
-
"jsonwebtoken": "^9.0.
|
|
63
|
+
"jsonwebtoken": "^9.0.3",
|
|
64
|
+
"jwks-rsa": "^3.2.2",
|
|
64
65
|
"ms": "^2.1.3"
|
|
65
66
|
},
|
|
66
67
|
"peerDependencies": {
|
|
@@ -97,4 +98,4 @@
|
|
|
97
98
|
"tests/**"
|
|
98
99
|
]
|
|
99
100
|
}
|
|
100
|
-
}
|
|
101
|
+
}
|