@maximemrf/adonisjs-jwt 0.7.0 → 0.8.0-alpha.0
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 +18 -0
- package/build/src/define_config.d.ts +5 -4
- package/build/src/define_config.js +1 -0
- package/build/src/jwks.d.ts +1 -1
- package/build/src/jwt.d.ts +2 -2
- package/build/src/jwt.js +12 -11
- package/build/src/types.d.ts +6 -3
- package/build/src/types.js +1 -1
- package/package.json +26 -18
package/README.md
CHANGED
|
@@ -79,6 +79,11 @@ const authConfig = defineConfig({
|
|
|
79
79
|
refreshTokenExpiresIn: '7d',
|
|
80
80
|
// ability to separate cookie usage for refresh token
|
|
81
81
|
useCookiesForRefreshToken: true,
|
|
82
|
+
// ability to configure the cookies options
|
|
83
|
+
cookie: {
|
|
84
|
+
httpOnly: true,
|
|
85
|
+
secure: true,
|
|
86
|
+
},
|
|
82
87
|
// limit the abilities of the refresh token
|
|
83
88
|
refreshTokenAbilities: ['refresh_token'],
|
|
84
89
|
// 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
|
|
@@ -116,6 +121,19 @@ useCookies: true
|
|
|
116
121
|
|
|
117
122
|
If you just want to use jwt with the bearer token no need to set `useCookies` to `false` you can just remove it.
|
|
118
123
|
|
|
124
|
+
You can also pass options to the cookies. Note that `maxAge` and `expires` are omitted from the options because they are automatically handled by the package based on the token validity (`tokenExpiresIn` and `refreshTokenExpiresIn`).
|
|
125
|
+
By default, `httpOnly: true` and `secure: true` are enforced for better security, but you can override them using the `cookie` object configuration.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
cookie: {
|
|
129
|
+
httpOnly: true, // Default
|
|
130
|
+
secure: true, // Default
|
|
131
|
+
path: '/',
|
|
132
|
+
sameSite: 'lax',
|
|
133
|
+
// maxAge and expires cannot be set here
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
119
137
|
## JWKS
|
|
120
138
|
|
|
121
139
|
You can use JWKS to verify the token by setting the `jwks` option in the guard configuration.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { GuardConfigProvider } from '@adonisjs/auth/types';
|
|
1
|
+
import type { GuardConfigProvider } from '@adonisjs/auth/types';
|
|
2
2
|
import type { HttpContext } from '@adonisjs/core/http';
|
|
3
|
-
import { JwtGuardUser, JwtUserProviderContract } from './types.js';
|
|
3
|
+
import type { JwtGuardUser, JwtUserProviderContract, JwtCookieOptions } from './types.js';
|
|
4
4
|
import { JwtGuard } from './jwt.js';
|
|
5
5
|
import type { StringValue } from 'ms';
|
|
6
|
-
import { AccessTokensUserProviderContract } from '@adonisjs/auth/types/access_tokens';
|
|
7
|
-
import { Options } from 'jwks-rsa';
|
|
6
|
+
import type { AccessTokensUserProviderContract } from '@adonisjs/auth/types/access_tokens';
|
|
7
|
+
import type { Options } from 'jwks-rsa';
|
|
8
8
|
export declare function jwtGuard<UserProvider extends JwtUserProviderContract<unknown>>(config: {
|
|
9
9
|
provider: UserProvider;
|
|
10
10
|
refreshTokenUserProvider?: AccessTokensUserProviderContract<unknown>;
|
|
@@ -17,4 +17,5 @@ export declare function jwtGuard<UserProvider extends JwtUserProviderContract<un
|
|
|
17
17
|
secret?: string;
|
|
18
18
|
content: <T>(user: JwtGuardUser<T>) => Record<string | number, any>;
|
|
19
19
|
jwks?: Options;
|
|
20
|
+
cookie?: JwtCookieOptions;
|
|
20
21
|
}): GuardConfigProvider<(ctx: HttpContext) => JwtGuard<UserProvider>>;
|
package/build/src/jwks.d.ts
CHANGED
package/build/src/jwt.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { symbols } from '@adonisjs/auth';
|
|
2
|
-
import { AuthClientResponse, GuardContract } from '@adonisjs/auth/types';
|
|
2
|
+
import type { AuthClientResponse, GuardContract } from '@adonisjs/auth/types';
|
|
3
3
|
import type { HttpContext } from '@adonisjs/core/http';
|
|
4
4
|
import type { StringValue } from 'ms';
|
|
5
|
-
import { JwtUserProviderContract, JwtGuardOptions } from './types.js';
|
|
5
|
+
import type { JwtUserProviderContract, JwtGuardOptions } from './types.js';
|
|
6
6
|
export declare class JwtGuard<UserProvider extends JwtUserProviderContract<unknown>> implements GuardContract<UserProvider[typeof symbols.PROVIDER_REAL_USER]> {
|
|
7
7
|
#private;
|
|
8
8
|
constructor(ctx: HttpContext, userProvider: UserProvider, option: JwtGuardOptions<UserProvider[typeof symbols.PROVIDER_REAL_USER]>);
|
package/build/src/jwt.js
CHANGED
|
@@ -10,6 +10,7 @@ export class JwtGuard {
|
|
|
10
10
|
#tokenName;
|
|
11
11
|
#refreshTokenName = 'refreshToken';
|
|
12
12
|
#jwksManager;
|
|
13
|
+
#cookieOptions;
|
|
13
14
|
constructor(ctx, userProvider, option) {
|
|
14
15
|
this.#ctx = ctx;
|
|
15
16
|
this.#userProvider = userProvider;
|
|
@@ -19,6 +20,11 @@ export class JwtGuard {
|
|
|
19
20
|
this.#options.content = (user) => ({ userId: user.getId() });
|
|
20
21
|
this.#tokenName = this.#options.tokenName ?? 'token';
|
|
21
22
|
this.#jwksManager = this.#options.jwks ? new JwksManager(this.#options.jwks) : undefined;
|
|
23
|
+
this.#cookieOptions = {
|
|
24
|
+
httpOnly: true,
|
|
25
|
+
secure: true,
|
|
26
|
+
...this.#options.cookie,
|
|
27
|
+
};
|
|
22
28
|
}
|
|
23
29
|
/**
|
|
24
30
|
* A unique name for the guard driver
|
|
@@ -64,12 +70,14 @@ export class JwtGuard {
|
|
|
64
70
|
}
|
|
65
71
|
if (this.#options.useCookies) {
|
|
66
72
|
this.#ctx.response.cookie(`${this.#tokenName}`, token, {
|
|
67
|
-
|
|
73
|
+
...this.#cookieOptions,
|
|
74
|
+
maxAge: this.#options.expiresIn,
|
|
68
75
|
});
|
|
69
76
|
}
|
|
70
77
|
if (this.#options.useCookiesForRefreshToken && refreshToken) {
|
|
71
78
|
this.#ctx.response.cookie(`${this.#refreshTokenName}`, refreshToken, {
|
|
72
|
-
|
|
79
|
+
...this.#cookieOptions,
|
|
80
|
+
maxAge: this.#options.refreshTokenExpiresIn,
|
|
73
81
|
});
|
|
74
82
|
}
|
|
75
83
|
return {
|
|
@@ -94,17 +102,10 @@ export class JwtGuard {
|
|
|
94
102
|
return this.getUserOrFail();
|
|
95
103
|
}
|
|
96
104
|
this.authenticationAttempted = true;
|
|
97
|
-
const cookieHeader = this.#ctx.request.request.headers.cookie;
|
|
98
|
-
let token;
|
|
99
105
|
/**
|
|
100
|
-
*
|
|
106
|
+
* Try to read the token from the cookies.
|
|
101
107
|
*/
|
|
102
|
-
|
|
103
|
-
const regex = new RegExp(`${this.#tokenName}=([^;]*)`);
|
|
104
|
-
token =
|
|
105
|
-
this.#ctx.request.cookie(`${this.#tokenName}`) ??
|
|
106
|
-
(this.#ctx.request.request.headers.cookie.match(regex) || [])[1];
|
|
107
|
-
}
|
|
108
|
+
let token = this.#ctx.request.cookie(`${this.#tokenName}`);
|
|
108
109
|
/**
|
|
109
110
|
* If token is missing on cookies, then try to read it from the header authorization
|
|
110
111
|
*/
|
package/build/src/types.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { symbols } from '@adonisjs/auth';
|
|
1
|
+
import { type symbols } from '@adonisjs/auth';
|
|
2
2
|
import type { StringValue } from 'ms';
|
|
3
|
-
import { AccessTokensUserProviderContract } from '@adonisjs/auth/types/access_tokens';
|
|
4
|
-
import { Options } from 'jwks-rsa';
|
|
3
|
+
import type { AccessTokensUserProviderContract } from '@adonisjs/auth/types/access_tokens';
|
|
4
|
+
import type { Options } from 'jwks-rsa';
|
|
5
|
+
import type { CookieOptions } from '@adonisjs/core/types/http';
|
|
6
|
+
export type JwtCookieOptions = Omit<Partial<CookieOptions>, 'maxAge' | 'expires'>;
|
|
5
7
|
/**
|
|
6
8
|
* The bridge between the User provider and the
|
|
7
9
|
* Guard
|
|
@@ -49,5 +51,6 @@ export type JwtGuardOptions<RealUser extends any = unknown> = {
|
|
|
49
51
|
useCookies?: boolean;
|
|
50
52
|
useCookiesForRefreshToken?: boolean;
|
|
51
53
|
refreshTokenAbilities?: string[];
|
|
54
|
+
cookie?: JwtCookieOptions;
|
|
52
55
|
content?: (user: JwtGuardUser<RealUser>) => Record<string, any>;
|
|
53
56
|
};
|
package/build/src/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
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.
|
|
4
|
+
"version": "0.8.0-alpha.0",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.6.0"
|
|
7
7
|
},
|
|
@@ -17,13 +17,18 @@
|
|
|
17
17
|
"./types": "./build/src/types.js",
|
|
18
18
|
"./jwt_config": "./build/src/define_config.js"
|
|
19
19
|
},
|
|
20
|
+
"imports": {
|
|
21
|
+
"#generated/*": "./.adonisjs/server/*.js",
|
|
22
|
+
"#transformers/*": "./app/transformers/*.js",
|
|
23
|
+
"#database/*": "./database/*.js"
|
|
24
|
+
},
|
|
20
25
|
"scripts": {
|
|
21
26
|
"clean": "del-cli build",
|
|
22
27
|
"copy:templates": "copyfiles \"stubs/**/*.stub\" build",
|
|
23
28
|
"typecheck": "tsc --noEmit",
|
|
24
29
|
"lint": "eslint .",
|
|
25
30
|
"format": "prettier --write .",
|
|
26
|
-
"quick:test": "node --import
|
|
31
|
+
"quick:test": "node --import=@poppinss/ts-exec --enable-source-maps bin/test.ts --force-exit",
|
|
27
32
|
"pretest": "npm run lint",
|
|
28
33
|
"test": "c8 npm run quick:test",
|
|
29
34
|
"prebuild": "npm run lint && npm run clean",
|
|
@@ -34,31 +39,31 @@
|
|
|
34
39
|
"prepublishOnly": "npm run build"
|
|
35
40
|
},
|
|
36
41
|
"devDependencies": {
|
|
37
|
-
"@adonisjs/assembler": "^
|
|
38
|
-
"@adonisjs/auth": "^
|
|
39
|
-
"@adonisjs/core": "^
|
|
40
|
-
"@adonisjs/eslint-config": "^
|
|
41
|
-
"@adonisjs/lucid": "^
|
|
42
|
+
"@adonisjs/assembler": "^8.0.0",
|
|
43
|
+
"@adonisjs/auth": "^10.0.0",
|
|
44
|
+
"@adonisjs/core": "^7.0.1",
|
|
45
|
+
"@adonisjs/eslint-config": "^3.0.0",
|
|
46
|
+
"@adonisjs/lucid": "^22.0.0",
|
|
42
47
|
"@adonisjs/prettier-config": "^1.4.5",
|
|
43
|
-
"@adonisjs/tsconfig": "^
|
|
48
|
+
"@adonisjs/tsconfig": "^2.0.0",
|
|
44
49
|
"@japa/assert": "^4.2.0",
|
|
45
50
|
"@japa/file-system": "^3.0.0",
|
|
46
51
|
"@japa/runner": "^5.3.0",
|
|
47
|
-
"@
|
|
48
|
-
"@
|
|
52
|
+
"@poppinss/ts-exec": "^1.4.4",
|
|
53
|
+
"@types/nock": "^11.1.0",
|
|
49
54
|
"@types/node": "^22.15.18",
|
|
50
55
|
"c8": "^10.1.3",
|
|
51
56
|
"copyfiles": "^2.4.1",
|
|
52
57
|
"del-cli": "^7.0.0",
|
|
53
|
-
"eslint": "^9.39.
|
|
58
|
+
"eslint": "^9.39.3",
|
|
54
59
|
"luxon": "^3.7.2",
|
|
55
|
-
"nock": "^14.0.
|
|
56
|
-
"np": "^11.0.
|
|
60
|
+
"nock": "^14.0.11",
|
|
61
|
+
"np": "^11.0.2",
|
|
57
62
|
"prettier": "^3.8.1",
|
|
58
63
|
"sqlite3": "^5.1.7",
|
|
59
64
|
"timekeeper": "^2.3.1",
|
|
60
|
-
"
|
|
61
|
-
"
|
|
65
|
+
"typescript": "~5.9.3",
|
|
66
|
+
"youch": "^4.1.0"
|
|
62
67
|
},
|
|
63
68
|
"dependencies": {
|
|
64
69
|
"@types/jsonwebtoken": "^9.0.10",
|
|
@@ -67,7 +72,7 @@
|
|
|
67
72
|
"ms": "^2.1.3"
|
|
68
73
|
},
|
|
69
74
|
"peerDependencies": {
|
|
70
|
-
"@adonisjs/core": "^
|
|
75
|
+
"@adonisjs/core": "^7.0.1"
|
|
71
76
|
},
|
|
72
77
|
"author": "MaximeMRF",
|
|
73
78
|
"license": "MIT",
|
|
@@ -75,7 +80,10 @@
|
|
|
75
80
|
"adonisjs",
|
|
76
81
|
"adonis",
|
|
77
82
|
"jwt",
|
|
78
|
-
"authentication"
|
|
83
|
+
"authentication",
|
|
84
|
+
"jwks",
|
|
85
|
+
"refresh token",
|
|
86
|
+
"cookies"
|
|
79
87
|
],
|
|
80
88
|
"eslintConfig": {
|
|
81
89
|
"extends": "@adonisjs/eslint-config/package"
|
|
@@ -100,4 +108,4 @@
|
|
|
100
108
|
"tests/**"
|
|
101
109
|
]
|
|
102
110
|
}
|
|
103
|
-
}
|
|
111
|
+
}
|