@maximemrf/adonisjs-jwt 0.1.0 → 0.2.1

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
@@ -26,6 +26,8 @@ import { defineConfig } from '@adonisjs/auth'
26
26
  import { InferAuthEvents, Authenticators } from '@adonisjs/auth/types'
27
27
  import { sessionGuard, sessionUserProvider } from '@adonisjs/auth/session'
28
28
  import { jwtGuard } from '@maximemrf/adonisjs-jwt/jwt_config'
29
+ import { JwtGuardUser } from '@maximemrf/adonisjs-jwt/types'
30
+ import User from '#models/user'
29
31
 
30
32
  const authConfig = defineConfig({
31
33
  // define the default authenticator to jwt
@@ -46,6 +48,11 @@ const authConfig = defineConfig({
46
48
  provider: sessionUserProvider({
47
49
  model: () => import('#models/user'),
48
50
  }),
51
+ // content is a function that takes the user and returns the content of the token, it can be optional, by default it returns only the user id
52
+ content: (user: JwtGuardUser<User>) => ({
53
+ id: user.getId(),
54
+ email: user.getOriginal().email,
55
+ }),
49
56
  }),
50
57
  },
51
58
  })
@@ -93,3 +100,7 @@ router.get('/', async ({ auth }) => {
93
100
  })
94
101
  .use(middleware.auth({ guards: ['jwt'] }))
95
102
  ```
103
+
104
+ ## Security
105
+
106
+ We use natively the AdonisJS application key to sign the token, so you don't have to worry about it and [avoid this](https://trufflesecurity.com/blog/stop-recommending-jwts).
@@ -1,8 +1,10 @@
1
1
  import { GuardConfigProvider } from '@adonisjs/auth/types';
2
2
  import type { HttpContext } from '@adonisjs/core/http';
3
- import { JwtGuard, JwtUserProviderContract } from './jwt.js';
3
+ import { JwtGuardUser, JwtUserProviderContract } from './types.js';
4
+ import { JwtGuard } from './jwt.js';
4
5
  export declare function jwtGuard<UserProvider extends JwtUserProviderContract<unknown>>(config: {
5
6
  provider: UserProvider;
6
- tokenExpiresIn: number | string;
7
+ tokenExpiresIn?: number | string;
7
8
  useCookies?: boolean;
9
+ content: <T>(user: JwtGuardUser<T>) => Record<string, any>;
8
10
  }): GuardConfigProvider<(ctx: HttpContext) => JwtGuard<UserProvider>>;
@@ -7,6 +7,7 @@ export function jwtGuard(config) {
7
7
  secret: appKey,
8
8
  expiresIn: config.tokenExpiresIn,
9
9
  useCookies: config.useCookies,
10
+ content: config.content,
10
11
  };
11
12
  return (ctx) => new JwtGuard(ctx, config.provider, options);
12
13
  },
@@ -1,48 +1,10 @@
1
1
  import { symbols } from '@adonisjs/auth';
2
2
  import { AuthClientResponse, GuardContract } from '@adonisjs/auth/types';
3
3
  import type { HttpContext } from '@adonisjs/core/http';
4
- /**
5
- * The bridge between the User provider and the
6
- * Guard
7
- */
8
- export type JwtGuardUser<RealUser> = {
9
- /**
10
- * Returns the unique ID of the user
11
- */
12
- getId(): string | number | BigInt;
13
- /**
14
- * Returns the original user object
15
- */
16
- getOriginal(): RealUser;
17
- };
18
- /**
19
- * The interface for the UserProvider accepted by the
20
- * JWT guard.
21
- */
22
- export interface JwtUserProviderContract<RealUser> {
23
- /**
24
- * A property the guard implementation can use to infer
25
- * the data type of the actual user (aka RealUser)
26
- */
27
- [symbols.PROVIDER_REAL_USER]: RealUser;
28
- /**
29
- * Create a user object that acts as an adapter between
30
- * the guard and real user value.
31
- */
32
- createUserForGuard(user: RealUser): Promise<JwtGuardUser<RealUser>>;
33
- /**
34
- * Find a user by their id.
35
- */
36
- findById(identifier: string | number | BigInt): Promise<JwtGuardUser<RealUser> | null>;
37
- }
38
- export type JwtGuardOptions = {
39
- secret: string;
40
- expiresIn?: number | string;
41
- useCookies?: boolean;
42
- };
4
+ import { JwtUserProviderContract, JwtGuardOptions } from './types.js';
43
5
  export declare class JwtGuard<UserProvider extends JwtUserProviderContract<unknown>> implements GuardContract<UserProvider[typeof symbols.PROVIDER_REAL_USER]> {
44
6
  #private;
45
- constructor(ctx: HttpContext, userProvider: UserProvider, option: JwtGuardOptions);
7
+ constructor(ctx: HttpContext, userProvider: UserProvider, option: JwtGuardOptions<UserProvider[typeof symbols.PROVIDER_REAL_USER]>);
46
8
  /**
47
9
  * A list of events and their types emitted by
48
10
  * the guard.
package/build/src/jwt.js CHANGED
@@ -8,6 +8,8 @@ export class JwtGuard {
8
8
  this.#ctx = ctx;
9
9
  this.#userProvider = userProvider;
10
10
  this.#options = option;
11
+ if (!this.#options.content)
12
+ this.#options.content = (user) => ({ userId: user.getId() });
11
13
  }
12
14
  /**
13
15
  * A unique name for the guard driver
@@ -32,7 +34,7 @@ export class JwtGuard {
32
34
  */
33
35
  async generate(user) {
34
36
  const providerUser = await this.#userProvider.createUserForGuard(user);
35
- const token = jwt.sign({ userId: providerUser.getId() }, this.#options.secret, this.#options.expiresIn
37
+ const token = jwt.sign(this.#options.content(providerUser), this.#options.secret, this.#options.expiresIn
36
38
  ? {
37
39
  expiresIn: this.#options.expiresIn,
38
40
  }
@@ -68,9 +70,9 @@ export class JwtGuard {
68
70
  * If cookies are enabled, then read the token from the cookies
69
71
  */
70
72
  if (cookieHeader) {
71
- token = this.#ctx.request.cookie('token')
72
- ? this.#ctx.request.cookie('token')
73
- : (this.#ctx.request.request.headers.cookie.match(/token=(.*?)(;|$)/) || [])[1];
73
+ token =
74
+ this.#ctx.request.cookie('token') ??
75
+ (this.#ctx.request.request.headers.cookie.match(/token=(.*?)(;|$)/) || [])[1];
74
76
  }
75
77
  /**
76
78
  * If token is missing on cookies, then try to read it from the header authorization
@@ -0,0 +1,41 @@
1
+ import { symbols } from '@adonisjs/auth';
2
+ /**
3
+ * The bridge between the User provider and the
4
+ * Guard
5
+ */
6
+ export type JwtGuardUser<RealUser> = {
7
+ /**
8
+ * Returns the unique ID of the user
9
+ */
10
+ getId(): string | number | BigInt;
11
+ /**
12
+ * Returns the original user object
13
+ */
14
+ getOriginal(): RealUser;
15
+ };
16
+ /**
17
+ * The interface for the UserProvider accepted by the
18
+ * JWT guard.
19
+ */
20
+ export interface JwtUserProviderContract<RealUser> {
21
+ /**
22
+ * A property the guard implementation can use to infer
23
+ * the data type of the actual user (aka RealUser)
24
+ */
25
+ [symbols.PROVIDER_REAL_USER]: RealUser;
26
+ /**
27
+ * Create a user object that acts as an adapter between
28
+ * the guard and real user value.
29
+ */
30
+ createUserForGuard(user: RealUser): Promise<JwtGuardUser<RealUser>>;
31
+ /**
32
+ * Find a user by their id.
33
+ */
34
+ findById(identifier: string | number | BigInt): Promise<JwtGuardUser<RealUser> | null>;
35
+ }
36
+ export type JwtGuardOptions<RealUser extends any = unknown> = {
37
+ secret: string;
38
+ expiresIn?: number | string;
39
+ useCookies?: boolean;
40
+ content?: (user: JwtGuardUser<RealUser>) => Record<string, any>;
41
+ };
@@ -0,0 +1 @@
1
+ import { symbols } from '@adonisjs/auth';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maximemrf/adonisjs-jwt",
3
- "description": "",
4
- "version": "0.1.0",
3
+ "description": "Adonisjs v6 package for authentication with jwt token",
4
+ "version": "0.2.1",
5
5
  "engines": {
6
6
  "node": ">=20.6.0"
7
7
  },
@@ -33,9 +33,6 @@
33
33
  "version": "npm run build",
34
34
  "prepublishOnly": "npm run build"
35
35
  },
36
- "keywords": [],
37
- "author": "",
38
- "license": "MIT",
39
36
  "devDependencies": {
40
37
  "@adonisjs/assembler": "^7.2.3",
41
38
  "@adonisjs/auth": "^9.1.1",
@@ -59,9 +56,25 @@
59
56
  "ts-node": "^10.9.2",
60
57
  "typescript": "^5.4.2"
61
58
  },
59
+ "dependencies": {
60
+ "@types/jsonwebtoken": "^9.0.6",
61
+ "jsonwebtoken": "^9.0.2"
62
+ },
62
63
  "peerDependencies": {
63
64
  "@adonisjs/core": "^6.2.0"
64
65
  },
66
+ "author": "MaximeMRF",
67
+ "license": "MIT",
68
+ "keywords": [
69
+ "adonisjs",
70
+ "adonis",
71
+ "jwt",
72
+ "authentication"
73
+ ],
74
+ "eslintConfig": {
75
+ "extends": "@adonisjs/eslint-config/package"
76
+ },
77
+ "prettier": "@adonisjs/prettier-config",
65
78
  "publishConfig": {
66
79
  "access": "public",
67
80
  "tag": "latest"
@@ -80,13 +93,5 @@
80
93
  "exclude": [
81
94
  "tests/**"
82
95
  ]
83
- },
84
- "eslintConfig": {
85
- "extends": "@adonisjs/eslint-config/package"
86
- },
87
- "prettier": "@adonisjs/prettier-config",
88
- "dependencies": {
89
- "@types/jsonwebtoken": "^9.0.6",
90
- "jsonwebtoken": "^9.0.2"
91
96
  }
92
97
  }
@@ -1,5 +0,0 @@
1
- /**
2
- * Path to the root directory where the stubs are stored. We use
3
- * this path within commands and the configure hook
4
- */
5
- export declare const stubsRoot: string;
@@ -1,7 +0,0 @@
1
- import { dirname } from 'node:path';
2
- import { fileURLToPath } from 'node:url';
3
- /**
4
- * Path to the root directory where the stubs are stored. We use
5
- * this path within commands and the configure hook
6
- */
7
- export const stubsRoot = dirname(fileURLToPath(import.meta.url));