@devmoods/express-extras 0.43.0 → 0.44.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/dist/auth.d.ts +3 -1
- package/dist/auth.js +19 -12
- package/package.json +5 -5
package/dist/auth.d.ts
CHANGED
|
@@ -44,6 +44,7 @@ export interface AuthOptions<UserModel extends AnyUser> {
|
|
|
44
44
|
providers: AuthProvider<UserModel>[];
|
|
45
45
|
redis: RedisClient;
|
|
46
46
|
filterUser(user: UserModel): Partial<UserModel>;
|
|
47
|
+
loginUrl?: string;
|
|
47
48
|
}
|
|
48
49
|
export interface CreateAuth<UserModel extends AnyUser> {
|
|
49
50
|
createRouter: () => Router;
|
|
@@ -54,7 +55,7 @@ export interface CreateAuth<UserModel extends AnyUser> {
|
|
|
54
55
|
export type AuthMiddlewareOptions<UserModel extends AnyUser> = false | {
|
|
55
56
|
isAuthorized?: (user: UserModel) => Promise<boolean> | boolean;
|
|
56
57
|
};
|
|
57
|
-
export declare function createAuth<UserModel extends AnyUser>({ getUserByToken, filterUser, redis, providers, }: AuthOptions<UserModel>): CreateAuth<UserModel>;
|
|
58
|
+
export declare function createAuth<UserModel extends AnyUser>({ getUserByToken, filterUser, redis, providers, loginUrl, }: AuthOptions<UserModel>): CreateAuth<UserModel>;
|
|
58
59
|
/**
|
|
59
60
|
* Extract a Bearer token from the HTTP Authorization header
|
|
60
61
|
* of `req`.
|
|
@@ -66,6 +67,7 @@ export declare function parseAuthorizationHeader(req: Request): string | null;
|
|
|
66
67
|
* Checks multiple places and uses the first match. Priority:
|
|
67
68
|
* 1. Request header `Authorization: `
|
|
68
69
|
* 2. Cookie named `access_token`
|
|
70
|
+
*
|
|
69
71
|
*/
|
|
70
72
|
export declare function extractAccessTokenFromRequest(req: Request): string | null;
|
|
71
73
|
/**
|
package/dist/auth.js
CHANGED
|
@@ -5,7 +5,7 @@ import jwt from 'jsonwebtoken';
|
|
|
5
5
|
import { v4 } from 'uuid';
|
|
6
6
|
import { config } from './config.js';
|
|
7
7
|
import { setContext, useContext } from './context.js';
|
|
8
|
-
import {
|
|
8
|
+
import { BadRequest, Forbidden, NotFound, Unauthorized } from './errors.js';
|
|
9
9
|
import { getLogger } from './logger.js';
|
|
10
10
|
import { route } from './middleware.js';
|
|
11
11
|
import {} from './redis.js';
|
|
@@ -40,7 +40,7 @@ export function decodeAuthToken(token, secret = AUTH_SECRET) {
|
|
|
40
40
|
return { ...decoded };
|
|
41
41
|
}
|
|
42
42
|
catch (error) {
|
|
43
|
-
throw new
|
|
43
|
+
throw new InvalidToken(`Failed to decode auth token: ${error.message}`);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
export function EmailAndPasswordAuthProvider(options) {
|
|
@@ -140,7 +140,7 @@ export function EmailAndPasswordAuthProvider(options) {
|
|
|
140
140
|
},
|
|
141
141
|
};
|
|
142
142
|
}
|
|
143
|
-
export function createAuth({ getUserByToken, filterUser, redis, providers, }) {
|
|
143
|
+
export function createAuth({ getUserByToken, filterUser, redis, providers, loginUrl = '/', }) {
|
|
144
144
|
const useCurrentUser = () => useContext('currentUser');
|
|
145
145
|
const setCurrentUser = (user) => setContext('currentUser', user);
|
|
146
146
|
const login = async (res, user) => {
|
|
@@ -230,21 +230,27 @@ export function createAuth({ getUserByToken, filterUser, redis, providers, }) {
|
|
|
230
230
|
throw new InvalidToken('token expired');
|
|
231
231
|
}
|
|
232
232
|
const decoded = decodeAuthToken(token);
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
try {
|
|
234
|
+
const user = await getUserByToken(decoded);
|
|
235
|
+
if (options.isAuthorized && !(await options.isAuthorized(user))) {
|
|
236
|
+
throw Forbidden('Permission denied');
|
|
237
|
+
}
|
|
238
|
+
setCurrentUser(user);
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
throw new InvalidToken('User not found');
|
|
236
242
|
}
|
|
237
|
-
setCurrentUser(user);
|
|
238
243
|
next();
|
|
239
244
|
}
|
|
240
245
|
catch (error) {
|
|
241
246
|
logger.error(error);
|
|
242
|
-
if (error instanceof
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
247
|
+
if (error instanceof InvalidToken) {
|
|
248
|
+
if (req.accepts('html')) {
|
|
249
|
+
return res.redirect(loginUrl);
|
|
250
|
+
}
|
|
246
251
|
next(Unauthorized('Invalid token'));
|
|
247
252
|
}
|
|
253
|
+
next(error);
|
|
248
254
|
}
|
|
249
255
|
};
|
|
250
256
|
}
|
|
@@ -284,7 +290,7 @@ export function parseAuthorizationHeader(req) {
|
|
|
284
290
|
.split(' ')
|
|
285
291
|
.map((s) => s.trim());
|
|
286
292
|
if (token && type !== 'Bearer') {
|
|
287
|
-
throw new
|
|
293
|
+
throw new InvalidToken('Only Bearer type supported in jwt()');
|
|
288
294
|
}
|
|
289
295
|
// No token given, this is not necessarilly an error case
|
|
290
296
|
if (!token) {
|
|
@@ -302,6 +308,7 @@ export function parseAuthorizationHeader(req) {
|
|
|
302
308
|
* Checks multiple places and uses the first match. Priority:
|
|
303
309
|
* 1. Request header `Authorization: `
|
|
304
310
|
* 2. Cookie named `access_token`
|
|
311
|
+
*
|
|
305
312
|
*/
|
|
306
313
|
export function extractAccessTokenFromRequest(req) {
|
|
307
314
|
const authorizationHeader = parseAuthorizationHeader(req);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devmoods/express-extras",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.44.0",
|
|
4
4
|
"description": "Kubernetes-ready utilities for rapid Node.js application development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
],
|
|
19
19
|
"license": "ISC",
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@devmoods/eslint-config": "^2.
|
|
21
|
+
"@devmoods/eslint-config": "^2.5.0",
|
|
22
22
|
"@types/koa-compose": "^3.2.8",
|
|
23
23
|
"@types/node": "22.10.1",
|
|
24
24
|
"@types/supertest": "^6.0.2",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@devmoods/fetch": "^4.0.1",
|
|
39
|
-
"@sentry/node": "^8.
|
|
40
|
-
"@sentry/profiling-node": "^8.
|
|
39
|
+
"@sentry/node": "^8.43.0",
|
|
40
|
+
"@sentry/profiling-node": "^8.43.0",
|
|
41
41
|
"@types/bcrypt": "^5.0.2",
|
|
42
42
|
"@types/body-parser": "^1.19.5",
|
|
43
43
|
"@types/cookie-parser": "^1.4.8",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"compose-middleware": "^5.0.1",
|
|
56
56
|
"cookie-parser": "^1.4.7",
|
|
57
57
|
"dotenv": "^16.4.7",
|
|
58
|
-
"express": "^4.21.
|
|
58
|
+
"express": "^4.21.2",
|
|
59
59
|
"helmet": "^8.0.0",
|
|
60
60
|
"jsonwebtoken": "^9.0.2",
|
|
61
61
|
"nodemailer": "^6.9.16",
|