@flink-app/jwt-auth-plugin 2.0.0-alpha.95 → 2.0.0-alpha.97
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/CHANGELOG.md +39 -0
- package/dist/FlinkJwtAuthPlugin.d.ts +9 -1
- package/dist/FlinkJwtAuthPlugin.js +8 -7
- package/package.json +3 -3
- package/src/FlinkJwtAuthPlugin.ts +15 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# @flink-app/jwt-auth-plugin
|
|
2
2
|
|
|
3
|
+
## 2.0.0-alpha.97
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- eed6bc1: Pass host application context to auth plugins.
|
|
8
|
+
|
|
9
|
+
`FlinkAuthPlugin.authenticateRequest` now receives the host app's context as an optional third argument. Flink core supplies it on every authenticated request, so auth plugins can access repos/services without the caller wiring up a lazy accessor or maintaining a module-level mutable reference.
|
|
10
|
+
|
|
11
|
+
For `@flink-app/jwt-auth-plugin`, this means `getUser` receives the context directly:
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
jwtAuthPlugin({
|
|
15
|
+
getUser: async (tokenData, req, ctx) => {
|
|
16
|
+
const user = await ctx?.repos.userRepo.getById(tokenData._id);
|
|
17
|
+
return user ? { username: user.username, _id: user._id } : null;
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The `getContext` option previously added in alpha.96 is no longer needed and has been removed — remove it from your `jwtAuthPlugin({ … })` call. The third `ctx` parameter on `getUser` is optional, so callbacks that ignore it are unaffected.
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- Updated dependencies [eed6bc1]
|
|
27
|
+
- @flink-app/flink@2.0.0-alpha.97
|
|
28
|
+
|
|
29
|
+
## 2.0.0-alpha.96
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- e431237: Add `iat` (issued-at) claim to generated JWTs.
|
|
34
|
+
|
|
35
|
+
`iat` is a standard JWT claim that records when the token was issued (Unix seconds). Adding it enables consumers to implement stateless force-logout / token-revocation patterns by storing a per-user "tokens-valid-from" timestamp and rejecting any token whose `iat` is older.
|
|
36
|
+
|
|
37
|
+
Backwards compatible — the claim is informational and does not affect verification of existing tokens. If a caller's payload already contains an `iat` field it takes precedence (useful for tests).
|
|
38
|
+
|
|
39
|
+
- Updated dependencies
|
|
40
|
+
- @flink-app/flink@2.0.0-alpha.96
|
|
41
|
+
|
|
3
42
|
## 2.0.0-alpha.95
|
|
4
43
|
|
|
5
44
|
### Patch Changes
|
|
@@ -33,7 +33,15 @@ export type TokenTTLResolver = (roles: string[], payload: any) => number | undef
|
|
|
33
33
|
export interface JwtAuthPluginOptions {
|
|
34
34
|
secret: string;
|
|
35
35
|
algo?: jwtSimple.TAlgorithm;
|
|
36
|
-
|
|
36
|
+
/**
|
|
37
|
+
* @param ctx The host application's context, supplied by Flink core on
|
|
38
|
+
* each authenticated request. Lets the callback access repos/services
|
|
39
|
+
* that don't exist when the plugin is constructed (e.g. before
|
|
40
|
+
* `FlinkApp.start()` resolves) without forcing the consumer to keep a
|
|
41
|
+
* module-level mutable reference. Undefined only when invoked outside
|
|
42
|
+
* the normal request pipeline (e.g. unit tests).
|
|
43
|
+
*/
|
|
44
|
+
getUser: (tokenData: any, req: FlinkRequest, ctx?: any) => Promise<FlinkAuthUser | null | undefined>;
|
|
37
45
|
passwordPolicy?: RegExp;
|
|
38
46
|
tokenTTL?: number;
|
|
39
47
|
rolePermissions: {
|
|
@@ -67,9 +67,9 @@ function jwtAuthPlugin(_a) {
|
|
|
67
67
|
var _this = this;
|
|
68
68
|
var secret = _a.secret, getUser = _a.getUser, rolePermissions = _a.rolePermissions, _b = _a.algo, algo = _b === void 0 ? "HS256" : _b, _c = _a.passwordPolicy, passwordPolicy = _c === void 0 ? defaultPasswordPolicy : _c, tokenTTL = _a.tokenTTL, tokenExtractor = _a.tokenExtractor, checkPermissions = _a.checkPermissions, _d = _a.useDynamicRoles, useDynamicRoles = _d === void 0 ? false : _d, resolveTokenTTL = _a.resolveTokenTTL;
|
|
69
69
|
return {
|
|
70
|
-
authenticateRequest: function (req, permissions) { return __awaiter(_this, void 0, void 0, function () {
|
|
70
|
+
authenticateRequest: function (req, permissions, ctx) { return __awaiter(_this, void 0, void 0, function () {
|
|
71
71
|
return __generator(this, function (_a) {
|
|
72
|
-
return [2 /*return*/, authenticateRequest(req, permissions, rolePermissions, {
|
|
72
|
+
return [2 /*return*/, authenticateRequest(req, permissions, rolePermissions, ctx, {
|
|
73
73
|
algo: algo,
|
|
74
74
|
secret: secret,
|
|
75
75
|
getUser: getUser,
|
|
@@ -84,8 +84,8 @@ function jwtAuthPlugin(_a) {
|
|
|
84
84
|
validatePassword: validatePassword,
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
|
-
function authenticateRequest(req_1, routePermissions_1, rolePermissions_1, _a) {
|
|
88
|
-
return __awaiter(this, arguments, void 0, function (req, routePermissions, rolePermissions, _b) {
|
|
87
|
+
function authenticateRequest(req_1, routePermissions_1, rolePermissions_1, ctx_1, _a) {
|
|
88
|
+
return __awaiter(this, arguments, void 0, function (req, routePermissions, rolePermissions, ctx, _b) {
|
|
89
89
|
var token, decodedToken, permissionsArr, validPerms, user, validPerms, hasPermission;
|
|
90
90
|
var secret = _b.secret, algo = _b.algo, getUser = _b.getUser, tokenExtractor = _b.tokenExtractor, checkPermissions = _b.checkPermissions, useDynamicRoles = _b.useDynamicRoles;
|
|
91
91
|
return __generator(this, function (_c) {
|
|
@@ -122,7 +122,7 @@ function authenticateRequest(req_1, routePermissions_1, rolePermissions_1, _a) {
|
|
|
122
122
|
return [2 /*return*/, false];
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
-
return [4 /*yield*/, getUser(decodedToken, req)];
|
|
125
|
+
return [4 /*yield*/, getUser(decodedToken, req, ctx)];
|
|
126
126
|
case 1:
|
|
127
127
|
user = _c.sent();
|
|
128
128
|
if (!user) {
|
|
@@ -170,7 +170,7 @@ function getTokenFromReq(req) {
|
|
|
170
170
|
}
|
|
171
171
|
function createToken(payload_1, _a, roles_1) {
|
|
172
172
|
return __awaiter(this, arguments, void 0, function (payload, _b, roles) {
|
|
173
|
-
var resolvedTTL, effectiveTTL;
|
|
173
|
+
var resolvedTTL, effectiveTTL, iat;
|
|
174
174
|
var _c;
|
|
175
175
|
var secret = _b.secret, algo = _b.algo, tokenTTL = _b.tokenTTL, resolveTokenTTL = _b.resolveTokenTTL;
|
|
176
176
|
return __generator(this, function (_d) {
|
|
@@ -179,7 +179,8 @@ function createToken(payload_1, _a, roles_1) {
|
|
|
179
179
|
}
|
|
180
180
|
resolvedTTL = resolveTokenTTL === null || resolveTokenTTL === void 0 ? void 0 : resolveTokenTTL(roles, payload);
|
|
181
181
|
effectiveTTL = (_c = resolvedTTL !== null && resolvedTTL !== void 0 ? resolvedTTL : tokenTTL) !== null && _c !== void 0 ? _c : 1000 * 60 * 60 * 24 * 365 * 100;
|
|
182
|
-
|
|
182
|
+
iat = Math.floor(Date.now() / 1000);
|
|
183
|
+
return [2 /*return*/, jwt_simple_1.default.encode(__assign({ iat: iat, exp: _calculateExpiration(effectiveTTL) }, payload), secret, algo)];
|
|
183
184
|
});
|
|
184
185
|
});
|
|
185
186
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flink-app/jwt-auth-plugin",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.97",
|
|
4
4
|
"description": "Flink plugin for JWT auth",
|
|
5
5
|
"author": "joel@frost.se",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
"@types/node": "22.13.10",
|
|
20
20
|
"ts-node": "^10.9.2",
|
|
21
21
|
"tsc-watch": "^4.2.9",
|
|
22
|
-
"@flink-app/flink": "2.0.0-alpha.
|
|
22
|
+
"@flink-app/flink": "2.0.0-alpha.97"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"@flink-app/flink": ">=2.0.0-alpha.
|
|
25
|
+
"@flink-app/flink": ">=2.0.0-alpha.97"
|
|
26
26
|
},
|
|
27
27
|
"gitHead": "4243e3b3cd6d4e1ca001a61baa8436bf2bbe4113",
|
|
28
28
|
"scripts": {
|
|
@@ -48,7 +48,15 @@ export type TokenTTLResolver = (roles: string[], payload: any) => number | undef
|
|
|
48
48
|
export interface JwtAuthPluginOptions {
|
|
49
49
|
secret: string;
|
|
50
50
|
algo?: jwtSimple.TAlgorithm;
|
|
51
|
-
|
|
51
|
+
/**
|
|
52
|
+
* @param ctx The host application's context, supplied by Flink core on
|
|
53
|
+
* each authenticated request. Lets the callback access repos/services
|
|
54
|
+
* that don't exist when the plugin is constructed (e.g. before
|
|
55
|
+
* `FlinkApp.start()` resolves) without forcing the consumer to keep a
|
|
56
|
+
* module-level mutable reference. Undefined only when invoked outside
|
|
57
|
+
* the normal request pipeline (e.g. unit tests).
|
|
58
|
+
*/
|
|
59
|
+
getUser: (tokenData: any, req: FlinkRequest, ctx?: any) => Promise<FlinkAuthUser | null | undefined>;
|
|
52
60
|
passwordPolicy?: RegExp;
|
|
53
61
|
tokenTTL?: number;
|
|
54
62
|
rolePermissions: {
|
|
@@ -150,8 +158,8 @@ export function jwtAuthPlugin({
|
|
|
150
158
|
resolveTokenTTL,
|
|
151
159
|
}: JwtAuthPluginOptions): JwtAuthPlugin {
|
|
152
160
|
return {
|
|
153
|
-
authenticateRequest: async (req, permissions) =>
|
|
154
|
-
authenticateRequest(req, permissions, rolePermissions, {
|
|
161
|
+
authenticateRequest: async (req, permissions, ctx) =>
|
|
162
|
+
authenticateRequest(req, permissions, rolePermissions, ctx, {
|
|
155
163
|
algo,
|
|
156
164
|
secret,
|
|
157
165
|
getUser,
|
|
@@ -169,6 +177,7 @@ async function authenticateRequest(
|
|
|
169
177
|
req: FlinkRequest,
|
|
170
178
|
routePermissions: string | string[],
|
|
171
179
|
rolePermissions: { [x: string]: string[] },
|
|
180
|
+
ctx: any,
|
|
172
181
|
{ secret, algo, getUser, tokenExtractor, checkPermissions, useDynamicRoles }: Pick<
|
|
173
182
|
JwtAuthPluginOptions,
|
|
174
183
|
"algo" | "secret" | "getUser" | "tokenExtractor" | "checkPermissions" | "useDynamicRoles"
|
|
@@ -212,7 +221,7 @@ async function authenticateRequest(
|
|
|
212
221
|
}
|
|
213
222
|
}
|
|
214
223
|
|
|
215
|
-
const user = await getUser(decodedToken, req);
|
|
224
|
+
const user = await getUser(decodedToken, req, ctx);
|
|
216
225
|
|
|
217
226
|
if (!user) {
|
|
218
227
|
log.debug("[JWT AUTH PLUGIN] User not returned from getUser callback");
|
|
@@ -274,8 +283,9 @@ async function createToken(
|
|
|
274
283
|
|
|
275
284
|
const resolvedTTL = resolveTokenTTL?.(roles, payload);
|
|
276
285
|
const effectiveTTL = resolvedTTL ?? tokenTTL ?? 1000 * 60 * 60 * 24 * 365 * 100;
|
|
286
|
+
const iat = Math.floor(Date.now() / 1000);
|
|
277
287
|
|
|
278
|
-
return jwtSimple.encode({ exp: _calculateExpiration(effectiveTTL), ...payload }, secret, algo);
|
|
288
|
+
return jwtSimple.encode({ iat, exp: _calculateExpiration(effectiveTTL), ...payload }, secret, algo);
|
|
279
289
|
}
|
|
280
290
|
|
|
281
291
|
function _calculateExpiration(expiresInMs: number) {
|