@maximemrf/adonisjs-jwt 0.7.0-alpha.1 → 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 CHANGED
@@ -199,16 +199,18 @@ router.post('login', async ({ request, auth }) => {
199
199
  })
200
200
 
201
201
  // if the jwt guard is the default guard
202
- router.get('/', async ({ auth }) => {
203
- return auth.getUserOrFail()
204
- })
205
- .use(middleware.auth())
202
+ router
203
+ .get('/', async ({ auth }) => {
204
+ return auth.getUserOrFail()
205
+ })
206
+ .use(middleware.auth())
206
207
 
207
208
  // if the jwt guard is not the default guard
208
- router.get('/', async ({ auth }) => {
209
- return auth.use('jwt').getUserOrFail()
210
- })
211
- .use(middleware.auth({ guards: ['jwt'] }))
209
+ router
210
+ .get('/', async ({ auth }) => {
211
+ return auth.use('jwt').getUserOrFail()
212
+ })
213
+ .use(middleware.auth({ guards: ['jwt'] }))
212
214
 
213
215
  // if you use the refresh token
214
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,7 @@
1
+ import { Options, JwksClient } from 'jwks-rsa';
2
+ export declare class JwksManager {
3
+ private client;
4
+ constructor(options: Options);
5
+ getClient(): JwksClient;
6
+ getSigningKey(kid: string): Promise<string>;
7
+ }
@@ -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
- payload = jwt.verify(token, this.#options.secret);
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
  });
@@ -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.1",
4
+ "version": "0.7.0-alpha.2",
5
5
  "engines": {
6
6
  "node": ">=20.6.0"
7
7
  },
@@ -61,6 +61,7 @@
61
61
  "dependencies": {
62
62
  "@types/jsonwebtoken": "^9.0.10",
63
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
+ }