@meridianjs/auth 0.1.3 → 0.1.4

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/dist/index.d.mts CHANGED
@@ -28,6 +28,7 @@ interface JwtPayload {
28
28
  workspaceId: string | null;
29
29
  roles: string[];
30
30
  permissions: string[];
31
+ jti?: string;
31
32
  iat?: number;
32
33
  exp?: number;
33
34
  }
@@ -49,11 +50,9 @@ declare class AuthModuleService extends AuthModuleService_base {
49
50
  /**
50
51
  * Express middleware that validates a Bearer JWT on every request.
51
52
  *
52
- * On success, populates req.user = { id, workspaceId, roles } and calls next().
53
+ * On success, populates req.user = { id, workspaceId, roles, permissions, jti } and calls next().
54
+ * Also validates the session against the DB (stateful revocation support).
53
55
  * On failure, responds 401 Unauthorized.
54
- *
55
- * Reads jwtSecret from req.scope (the request-scoped DI container that is
56
- * attached by the framework before any middleware runs).
57
56
  */
58
57
  declare function authenticateJWT(req: any, res: Response, next: NextFunction): void;
59
58
 
package/dist/index.d.ts CHANGED
@@ -28,6 +28,7 @@ interface JwtPayload {
28
28
  workspaceId: string | null;
29
29
  roles: string[];
30
30
  permissions: string[];
31
+ jti?: string;
31
32
  iat?: number;
32
33
  exp?: number;
33
34
  }
@@ -49,11 +50,9 @@ declare class AuthModuleService extends AuthModuleService_base {
49
50
  /**
50
51
  * Express middleware that validates a Bearer JWT on every request.
51
52
  *
52
- * On success, populates req.user = { id, workspaceId, roles } and calls next().
53
+ * On success, populates req.user = { id, workspaceId, roles, permissions, jti } and calls next().
54
+ * Also validates the session against the DB (stateful revocation support).
53
55
  * On failure, responds 401 Unauthorized.
54
- *
55
- * Reads jwtSecret from req.scope (the request-scoped DI container that is
56
- * attached by the framework before any middleware runs).
57
56
  */
58
57
  declare function authenticateJWT(req: any, res: Response, next: NextFunction): void;
59
58
 
package/dist/index.js CHANGED
@@ -45,8 +45,10 @@ var import_framework_utils2 = require("@meridianjs/framework-utils");
45
45
  var import_framework_utils = require("@meridianjs/framework-utils");
46
46
  var import_bcrypt = __toESM(require("bcrypt"));
47
47
  var import_jsonwebtoken = __toESM(require("jsonwebtoken"));
48
+ var import_crypto = require("crypto");
48
49
  var BCRYPT_ROUNDS = 12;
49
50
  var JWT_EXPIRES_IN = "7d";
51
+ var JWT_EXPIRES_MS = 7 * 24 * 60 * 60 * 1e3;
50
52
  var AuthModuleService = class extends (0, import_framework_utils.MeridianService)({}) {
51
53
  container;
52
54
  constructor(container) {
@@ -76,7 +78,9 @@ var AuthModuleService = class extends (0, import_framework_utils.MeridianService
76
78
  is_active: true
77
79
  });
78
80
  const permissions = await this.resolvePermissions(user.app_role_id);
79
- const token = this.signToken(user.id, null, [user.role], permissions, config.projectConfig.jwtSecret);
81
+ const { token, jti, expiresAt } = this.signToken(user.id, null, [user.role], permissions, config.projectConfig.jwtSecret);
82
+ await userService.createSession(jti, user.id, expiresAt).catch(() => {
83
+ });
80
84
  return {
81
85
  user: {
82
86
  id: user.id,
@@ -105,7 +109,9 @@ var AuthModuleService = class extends (0, import_framework_utils.MeridianService
105
109
  await userService.recordLogin(user.id).catch(() => {
106
110
  });
107
111
  const permissions = await this.resolvePermissions(user.app_role_id);
108
- const token = this.signToken(user.id, null, [user.role ?? "member"], permissions, config.projectConfig.jwtSecret);
112
+ const { token, jti, expiresAt } = this.signToken(user.id, null, [user.role ?? "member"], permissions, config.projectConfig.jwtSecret);
113
+ await userService.createSession(jti, user.id, expiresAt).catch(() => {
114
+ });
109
115
  return {
110
116
  user: {
111
117
  id: user.id,
@@ -131,9 +137,12 @@ var AuthModuleService = class extends (0, import_framework_utils.MeridianService
131
137
  }
132
138
  }
133
139
  signToken(userId, workspaceId, roles, permissions, secret) {
134
- return import_jsonwebtoken.default.sign({ sub: userId, workspaceId, roles, permissions }, secret, {
140
+ const jti = (0, import_crypto.randomUUID)();
141
+ const expiresAt = new Date(Date.now() + JWT_EXPIRES_MS);
142
+ const token = import_jsonwebtoken.default.sign({ sub: userId, workspaceId, roles, permissions, jti }, secret, {
135
143
  expiresIn: JWT_EXPIRES_IN
136
144
  });
145
+ return { token, jti, expiresAt };
137
146
  }
138
147
  };
139
148
 
@@ -146,26 +155,42 @@ function authenticateJWT(req, res, next) {
146
155
  res.status(401).json({ error: { message: "Unauthorized \u2014 Bearer token required" } });
147
156
  return;
148
157
  }
149
- let config;
150
- try {
151
- const scope = req.scope;
152
- config = scope.resolve("config");
153
- } catch {
154
- res.status(500).json({ error: { message: "Server misconfiguration" } });
155
- return;
156
- }
157
- try {
158
- const payload = import_jsonwebtoken2.default.verify(token, config.projectConfig.jwtSecret);
159
- req.user = {
160
- id: payload.sub,
161
- workspaceId: payload.workspaceId ?? null,
162
- roles: Array.isArray(payload.roles) ? payload.roles : [],
163
- permissions: Array.isArray(payload.permissions) ? payload.permissions : []
164
- };
165
- next();
166
- } catch {
167
- res.status(401).json({ error: { message: "Invalid or expired token" } });
168
- }
158
+ ;
159
+ (async () => {
160
+ let config;
161
+ try {
162
+ const scope = req.scope;
163
+ config = scope.resolve("config");
164
+ } catch {
165
+ res.status(500).json({ error: { message: "Server misconfiguration" } });
166
+ return;
167
+ }
168
+ try {
169
+ const payload = import_jsonwebtoken2.default.verify(token, config.projectConfig.jwtSecret);
170
+ if (payload.jti) {
171
+ try {
172
+ const scope = req.scope;
173
+ const userService = scope.resolve("userModuleService");
174
+ const valid = await userService.isSessionValid(payload.jti);
175
+ if (!valid) {
176
+ res.status(401).json({ error: { message: "Session revoked or expired" } });
177
+ return;
178
+ }
179
+ } catch {
180
+ }
181
+ }
182
+ req.user = {
183
+ id: payload.sub,
184
+ workspaceId: payload.workspaceId ?? null,
185
+ roles: Array.isArray(payload.roles) ? payload.roles : [],
186
+ permissions: Array.isArray(payload.permissions) ? payload.permissions : [],
187
+ jti: payload.jti ?? null
188
+ };
189
+ next();
190
+ } catch {
191
+ res.status(401).json({ error: { message: "Invalid or expired token" } });
192
+ }
193
+ })();
169
194
  }
170
195
 
171
196
  // src/guards.ts
package/dist/index.mjs CHANGED
@@ -5,8 +5,10 @@ import { Module } from "@meridianjs/framework-utils";
5
5
  import { MeridianService } from "@meridianjs/framework-utils";
6
6
  import bcrypt from "bcrypt";
7
7
  import jwt from "jsonwebtoken";
8
+ import { randomUUID } from "crypto";
8
9
  var BCRYPT_ROUNDS = 12;
9
10
  var JWT_EXPIRES_IN = "7d";
11
+ var JWT_EXPIRES_MS = 7 * 24 * 60 * 60 * 1e3;
10
12
  var AuthModuleService = class extends MeridianService({}) {
11
13
  container;
12
14
  constructor(container) {
@@ -36,7 +38,9 @@ var AuthModuleService = class extends MeridianService({}) {
36
38
  is_active: true
37
39
  });
38
40
  const permissions = await this.resolvePermissions(user.app_role_id);
39
- const token = this.signToken(user.id, null, [user.role], permissions, config.projectConfig.jwtSecret);
41
+ const { token, jti, expiresAt } = this.signToken(user.id, null, [user.role], permissions, config.projectConfig.jwtSecret);
42
+ await userService.createSession(jti, user.id, expiresAt).catch(() => {
43
+ });
40
44
  return {
41
45
  user: {
42
46
  id: user.id,
@@ -65,7 +69,9 @@ var AuthModuleService = class extends MeridianService({}) {
65
69
  await userService.recordLogin(user.id).catch(() => {
66
70
  });
67
71
  const permissions = await this.resolvePermissions(user.app_role_id);
68
- const token = this.signToken(user.id, null, [user.role ?? "member"], permissions, config.projectConfig.jwtSecret);
72
+ const { token, jti, expiresAt } = this.signToken(user.id, null, [user.role ?? "member"], permissions, config.projectConfig.jwtSecret);
73
+ await userService.createSession(jti, user.id, expiresAt).catch(() => {
74
+ });
69
75
  return {
70
76
  user: {
71
77
  id: user.id,
@@ -91,9 +97,12 @@ var AuthModuleService = class extends MeridianService({}) {
91
97
  }
92
98
  }
93
99
  signToken(userId, workspaceId, roles, permissions, secret) {
94
- return jwt.sign({ sub: userId, workspaceId, roles, permissions }, secret, {
100
+ const jti = randomUUID();
101
+ const expiresAt = new Date(Date.now() + JWT_EXPIRES_MS);
102
+ const token = jwt.sign({ sub: userId, workspaceId, roles, permissions, jti }, secret, {
95
103
  expiresIn: JWT_EXPIRES_IN
96
104
  });
105
+ return { token, jti, expiresAt };
97
106
  }
98
107
  };
99
108
 
@@ -106,26 +115,42 @@ function authenticateJWT(req, res, next) {
106
115
  res.status(401).json({ error: { message: "Unauthorized \u2014 Bearer token required" } });
107
116
  return;
108
117
  }
109
- let config;
110
- try {
111
- const scope = req.scope;
112
- config = scope.resolve("config");
113
- } catch {
114
- res.status(500).json({ error: { message: "Server misconfiguration" } });
115
- return;
116
- }
117
- try {
118
- const payload = jwt2.verify(token, config.projectConfig.jwtSecret);
119
- req.user = {
120
- id: payload.sub,
121
- workspaceId: payload.workspaceId ?? null,
122
- roles: Array.isArray(payload.roles) ? payload.roles : [],
123
- permissions: Array.isArray(payload.permissions) ? payload.permissions : []
124
- };
125
- next();
126
- } catch {
127
- res.status(401).json({ error: { message: "Invalid or expired token" } });
128
- }
118
+ ;
119
+ (async () => {
120
+ let config;
121
+ try {
122
+ const scope = req.scope;
123
+ config = scope.resolve("config");
124
+ } catch {
125
+ res.status(500).json({ error: { message: "Server misconfiguration" } });
126
+ return;
127
+ }
128
+ try {
129
+ const payload = jwt2.verify(token, config.projectConfig.jwtSecret);
130
+ if (payload.jti) {
131
+ try {
132
+ const scope = req.scope;
133
+ const userService = scope.resolve("userModuleService");
134
+ const valid = await userService.isSessionValid(payload.jti);
135
+ if (!valid) {
136
+ res.status(401).json({ error: { message: "Session revoked or expired" } });
137
+ return;
138
+ }
139
+ } catch {
140
+ }
141
+ }
142
+ req.user = {
143
+ id: payload.sub,
144
+ workspaceId: payload.workspaceId ?? null,
145
+ roles: Array.isArray(payload.roles) ? payload.roles : [],
146
+ permissions: Array.isArray(payload.permissions) ? payload.permissions : [],
147
+ jti: payload.jti ?? null
148
+ };
149
+ next();
150
+ } catch {
151
+ res.status(401).json({ error: { message: "Invalid or expired token" } });
152
+ }
153
+ })();
129
154
  }
130
155
 
131
156
  // src/guards.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meridianjs/auth",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Meridian auth module — JWT authentication and middleware",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",