@alanszp/express 6.0.3 → 7.0.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/.env.test +5 -0
- package/babel.config.js +7 -0
- package/dist/helpers/now.d.ts +1 -0
- package/dist/helpers/now.js +8 -0
- package/dist/helpers/now.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/middlewares/authenticateUser.d.ts +25 -0
- package/dist/middlewares/authenticateUser.js +114 -0
- package/dist/middlewares/authenticateUser.js.map +1 -0
- package/dist/middlewares/authenticateUser.test.d.ts +1 -0
- package/dist/middlewares/authenticateUser.test.js +308 -0
- package/dist/middlewares/authenticateUser.test.js.map +1 -0
- package/dist/middlewares/createContext.js +9 -7
- package/dist/middlewares/createContext.js.map +1 -1
- package/dist/test/mocks/authOptionsMocks.d.ts +8 -0
- package/dist/test/mocks/authOptionsMocks.js +30 -0
- package/dist/test/mocks/authOptionsMocks.js.map +1 -0
- package/dist/test/mocks/expressMocks.d.ts +5 -0
- package/dist/test/mocks/expressMocks.js +20 -0
- package/dist/test/mocks/expressMocks.js.map +1 -0
- package/dist/test/mocks/jwtUserMocks.d.ts +3 -0
- package/dist/test/mocks/jwtUserMocks.js +18 -0
- package/dist/test/mocks/jwtUserMocks.js.map +1 -0
- package/dist/test/setup.d.ts +1 -0
- package/dist/test/setup.js +5 -0
- package/dist/test/setup.js.map +1 -0
- package/dist/test/setup.test.d.ts +1 -0
- package/dist/test/setup.test.js +14 -0
- package/dist/test/setup.test.js.map +1 -0
- package/dist/types/AuthMethod.d.ts +1 -1
- package/jest.config.js +10 -0
- package/package.json +12 -7
- package/src/helpers/now.ts +3 -0
- package/src/index.ts +1 -1
- package/src/middlewares/authenticateUser.test.ts +403 -0
- package/src/middlewares/authenticateUser.ts +170 -0
- package/src/middlewares/createContext.ts +18 -14
- package/src/test/mocks/authOptionsMocks.ts +35 -0
- package/src/test/mocks/expressMocks.ts +17 -0
- package/src/test/mocks/jwtUserMocks.ts +17 -0
- package/src/test/setup.test.ts +15 -0
- package/src/test/setup.ts +3 -0
- package/src/types/AuthMethod.ts +4 -1
- package/tsconfig.json +5 -2
- package/dist/middlewares/authWithJWT.d.ts +0 -4
- package/dist/middlewares/authWithJWT.js +0 -56
- package/dist/middlewares/authWithJWT.js.map +0 -1
- package/src/middlewares/authWithJWT.ts +0 -54
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { JWTUser, verifyJWT, VerifyOptions } from "@alanszp/jwt";
|
|
2
|
+
import { UnauthorizedError } from "@alanszp/errors";
|
|
3
|
+
import { errorView } from "../views/errorView";
|
|
4
|
+
import { NextFunction, Response } from "express";
|
|
5
|
+
import { getRequestLogger } from "../helpers/getRequestLogger";
|
|
6
|
+
import { GenericRequest } from "../types/GenericRequest";
|
|
7
|
+
import { ILogger } from "@alanszp/logger";
|
|
8
|
+
import { compact, isEmpty, omit } from "lodash";
|
|
9
|
+
|
|
10
|
+
function parseAuthorizationHeader(
|
|
11
|
+
authorization: string | undefined
|
|
12
|
+
): string | undefined {
|
|
13
|
+
if (!authorization) return undefined;
|
|
14
|
+
const [bearer, jwt, ...other] = authorization.split(" ");
|
|
15
|
+
|
|
16
|
+
if (bearer !== "Bearer" || other.length > 0) return undefined;
|
|
17
|
+
|
|
18
|
+
return jwt;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export enum AuthMethods {
|
|
22
|
+
JWT = "JWT",
|
|
23
|
+
API_KEY = "API_KEY",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface JWTVerifyOptions extends VerifyOptions {
|
|
27
|
+
publicKey: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface JWTOptions {
|
|
31
|
+
jwtVerifyOptions: JWTVerifyOptions;
|
|
32
|
+
types: [AuthMethods.JWT];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ApiKeyOptions {
|
|
36
|
+
validApiKeys: string[];
|
|
37
|
+
types: [AuthMethods.API_KEY];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface BothMethodsOptions {
|
|
41
|
+
jwtVerifyOptions: JWTVerifyOptions;
|
|
42
|
+
validApiKeys: string[];
|
|
43
|
+
types:
|
|
44
|
+
| [AuthMethods.JWT, AuthMethods.API_KEY]
|
|
45
|
+
| [AuthMethods.API_KEY, AuthMethods.JWT];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type AuthOptions = JWTOptions | ApiKeyOptions | BothMethodsOptions;
|
|
49
|
+
|
|
50
|
+
const middlewareGetterByAuthType: Record<
|
|
51
|
+
AuthMethods,
|
|
52
|
+
(
|
|
53
|
+
tokenOrJwt: string | null | undefined,
|
|
54
|
+
options: AuthOptions,
|
|
55
|
+
logger: ILogger
|
|
56
|
+
) => Promise<JWTUser | null | undefined>
|
|
57
|
+
> = {
|
|
58
|
+
[AuthMethods.JWT]: async (
|
|
59
|
+
jwt: string | null | undefined,
|
|
60
|
+
options: Exclude<AuthOptions, ApiKeyOptions>,
|
|
61
|
+
logger: ILogger
|
|
62
|
+
) => {
|
|
63
|
+
try {
|
|
64
|
+
if (!jwt) return undefined;
|
|
65
|
+
const jwtUser = await verifyJWT(
|
|
66
|
+
options.jwtVerifyOptions.publicKey,
|
|
67
|
+
jwt,
|
|
68
|
+
omit(options.jwtVerifyOptions, "publicKey")
|
|
69
|
+
);
|
|
70
|
+
logger.debug("auth.authWithJwt.authed", {
|
|
71
|
+
user: jwtUser.id,
|
|
72
|
+
org: jwtUser.organizationReference,
|
|
73
|
+
});
|
|
74
|
+
return jwtUser;
|
|
75
|
+
} catch (error: unknown) {
|
|
76
|
+
logger.info("auth.authWithJwt.invalidJwt", { jwt, error });
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
[AuthMethods.API_KEY]: async (
|
|
81
|
+
token: string | null | undefined,
|
|
82
|
+
options: Exclude<AuthOptions, JWTOptions>,
|
|
83
|
+
logger: ILogger
|
|
84
|
+
): Promise<JWTUser | null | undefined> => {
|
|
85
|
+
try {
|
|
86
|
+
if (!token) return undefined;
|
|
87
|
+
if (options.validApiKeys.includes(token)) {
|
|
88
|
+
logger.debug("auth.authWithApiKey.authed", {
|
|
89
|
+
user: "0",
|
|
90
|
+
org: "lara",
|
|
91
|
+
});
|
|
92
|
+
return Promise.resolve({
|
|
93
|
+
id: "0",
|
|
94
|
+
employeeReference: "0",
|
|
95
|
+
organizationReference: "lara",
|
|
96
|
+
roles: [],
|
|
97
|
+
permissions: [],
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
} catch (error: unknown) {
|
|
103
|
+
logger.info("auth.authWithApiKey.invalidApiKey", { token, error });
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export function createAuthContext<Options extends AuthOptions>(
|
|
110
|
+
options: Options
|
|
111
|
+
) {
|
|
112
|
+
return function getMiddlewareForMethods(
|
|
113
|
+
authMethods: Options["types"][number][]
|
|
114
|
+
) {
|
|
115
|
+
return async function authWithGivenMethods(
|
|
116
|
+
req: GenericRequest,
|
|
117
|
+
res: Response,
|
|
118
|
+
next: NextFunction
|
|
119
|
+
): Promise<void> {
|
|
120
|
+
const logger = getRequestLogger(req);
|
|
121
|
+
const cookies = (req.cookies as Record<string, string | undefined>) || {};
|
|
122
|
+
const jwt =
|
|
123
|
+
cookies.jwt || parseAuthorizationHeader(req.headers.authorization);
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const authAttempts = await Promise.all(
|
|
127
|
+
authMethods.map((method) =>
|
|
128
|
+
middlewareGetterByAuthType[method](
|
|
129
|
+
method === AuthMethods.JWT ? jwt : req.headers.authorization,
|
|
130
|
+
options,
|
|
131
|
+
logger
|
|
132
|
+
)
|
|
133
|
+
)
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const successfulAuthAttempts = compact(authAttempts);
|
|
137
|
+
|
|
138
|
+
if (isEmpty(successfulAuthAttempts)) {
|
|
139
|
+
res
|
|
140
|
+
.status(401)
|
|
141
|
+
.json(
|
|
142
|
+
errorView(
|
|
143
|
+
new UnauthorizedError([
|
|
144
|
+
authAttempts.includes(null)
|
|
145
|
+
? `Token invalid for methods ${authMethods}`
|
|
146
|
+
: `Token not set for methods ${authMethods}`,
|
|
147
|
+
])
|
|
148
|
+
)
|
|
149
|
+
);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const jwtUser: JWTUser = successfulAuthAttempts[0];
|
|
154
|
+
req.context.jwtUser = jwtUser;
|
|
155
|
+
req.context.authenticated.push(
|
|
156
|
+
jwtUser.employeeReference !== "0" ? "jwt" : "api_key"
|
|
157
|
+
);
|
|
158
|
+
next();
|
|
159
|
+
} catch (error: unknown) {
|
|
160
|
+
logger.info("auth.authenticateUser.error", {
|
|
161
|
+
jwt,
|
|
162
|
+
token: req.headers.authorization,
|
|
163
|
+
methods: AuthMethods,
|
|
164
|
+
error,
|
|
165
|
+
});
|
|
166
|
+
res.status(401).json(errorView(new UnauthorizedError(authMethods)));
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
}
|
|
@@ -22,19 +22,23 @@ export function createContext(
|
|
|
22
22
|
|
|
23
23
|
const contextId = cuid();
|
|
24
24
|
|
|
25
|
-
sharedContext.run(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
25
|
+
sharedContext.run(
|
|
26
|
+
(context) => {
|
|
27
|
+
req.context.authenticated = [];
|
|
28
|
+
req.context.lifecycleId = context.lifecycleId;
|
|
29
|
+
req.context.lifecycleChain = context.lifecycleChain;
|
|
30
|
+
req.context.contextId = context.contextId;
|
|
31
|
+
req.context.log = context.logger;
|
|
32
|
+
req.context.audit = context.audit;
|
|
33
|
+
next();
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
logger: baseLogger,
|
|
37
|
+
audit: audit.withState(),
|
|
38
|
+
lifecycleId,
|
|
39
|
+
lifecycleChain,
|
|
40
|
+
contextId,
|
|
41
|
+
}
|
|
42
|
+
);
|
|
39
43
|
};
|
|
40
44
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ApiKeyOptions,
|
|
3
|
+
AuthMethods,
|
|
4
|
+
BothMethodsOptions,
|
|
5
|
+
JWTOptions,
|
|
6
|
+
} from "../../middlewares/authenticateUser";
|
|
7
|
+
|
|
8
|
+
export const jwtAuthOptions = {
|
|
9
|
+
jwtVerifyOptions: {
|
|
10
|
+
publicKey: "publicKey",
|
|
11
|
+
issuer: "issuer",
|
|
12
|
+
audience: "audience",
|
|
13
|
+
},
|
|
14
|
+
types: [AuthMethods.JWT],
|
|
15
|
+
} as any as JWTOptions;
|
|
16
|
+
|
|
17
|
+
export const verifyOptions = {
|
|
18
|
+
issuer: "issuer",
|
|
19
|
+
audience: "audience",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const apiKeyAuthOptions: ApiKeyOptions = {
|
|
23
|
+
validApiKeys: ["token", "tooooken"],
|
|
24
|
+
types: [AuthMethods.API_KEY],
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const bothMethodsAuthOptions: BothMethodsOptions = {
|
|
28
|
+
jwtVerifyOptions: {
|
|
29
|
+
publicKey: "publicKey",
|
|
30
|
+
issuer: "issuer",
|
|
31
|
+
audience: "audience",
|
|
32
|
+
},
|
|
33
|
+
validApiKeys: ["token", "tooooken"],
|
|
34
|
+
types: [AuthMethods.API_KEY, AuthMethods.JWT],
|
|
35
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { GenericRequest } from "../../types/GenericRequest";
|
|
2
|
+
|
|
3
|
+
export const mockRequest = (authorization: string): GenericRequest => {
|
|
4
|
+
return {
|
|
5
|
+
headers: { authorization },
|
|
6
|
+
context: { jwtUser: undefined, authenticated: [] },
|
|
7
|
+
} as any as GenericRequest;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const mockResponse = () => {
|
|
11
|
+
const res = {} as any;
|
|
12
|
+
res.status = jest.fn().mockReturnValue(res);
|
|
13
|
+
res.json = jest.fn().mockReturnValue(res);
|
|
14
|
+
return res;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const mockNext = () => jest.fn();
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { JWTUser } from "@alanszp/jwt";
|
|
2
|
+
|
|
3
|
+
export const userJwtUserMock: JWTUser = {
|
|
4
|
+
id: "1",
|
|
5
|
+
employeeReference: "1",
|
|
6
|
+
organizationReference: "test",
|
|
7
|
+
roles: [],
|
|
8
|
+
permissions: [],
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const laraJwtUserMock: JWTUser = {
|
|
12
|
+
id: "0",
|
|
13
|
+
employeeReference: "0",
|
|
14
|
+
organizationReference: "lara",
|
|
15
|
+
roles: [],
|
|
16
|
+
permissions: [],
|
|
17
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { now } from "../helpers/now";
|
|
2
|
+
|
|
3
|
+
jest.mock("@/helpers/now");
|
|
4
|
+
|
|
5
|
+
describe("Timezones", () => {
|
|
6
|
+
it("should always be UTC", () => {
|
|
7
|
+
expect(new Date().getTimezoneOffset()).toBe(0);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("now() is mocked", () => {
|
|
11
|
+
(now as jest.Mock).mockReturnValue(new Date("2021-01-01T12:30:43"));
|
|
12
|
+
|
|
13
|
+
expect(now()).toEqual(new Date("2021-01-01T12:30:43"));
|
|
14
|
+
});
|
|
15
|
+
});
|
package/src/types/AuthMethod.ts
CHANGED
|
@@ -21,4 +21,7 @@ type OverridableStringUnion<
|
|
|
21
21
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
22
22
|
export interface AuthMethodsOverride {}
|
|
23
23
|
|
|
24
|
-
export type AuthMethod = OverridableStringUnion<
|
|
24
|
+
export type AuthMethod = OverridableStringUnion<
|
|
25
|
+
"jwt" | "api_key",
|
|
26
|
+
AuthMethodsOverride
|
|
27
|
+
>;
|
package/tsconfig.json
CHANGED
|
@@ -4,12 +4,15 @@
|
|
|
4
4
|
"outDir": "dist",
|
|
5
5
|
"module": "commonjs",
|
|
6
6
|
"target": "es6",
|
|
7
|
-
"types": ["node"],
|
|
7
|
+
"types": ["jest", "node"],
|
|
8
8
|
"esModuleInterop": true,
|
|
9
9
|
"sourceMap": true,
|
|
10
10
|
|
|
11
11
|
"alwaysStrict": true,
|
|
12
12
|
"strictNullChecks": true
|
|
13
13
|
},
|
|
14
|
-
"exclude": ["node_modules"]
|
|
14
|
+
"exclude": ["node_modules"],
|
|
15
|
+
"paths": {
|
|
16
|
+
"@/*": ["src/*"]
|
|
17
|
+
}
|
|
15
18
|
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { VerifyOptions } from "@alanszp/jwt";
|
|
2
|
-
import { NextFunction, Response } from "express";
|
|
3
|
-
import { GenericRequest } from "../types/GenericRequest";
|
|
4
|
-
export declare function createAuthWithJWT(publicKey: string, options?: VerifyOptions): (req: GenericRequest, res: Response, next: NextFunction) => Promise<void>;
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.createAuthWithJWT = void 0;
|
|
13
|
-
const jwt_1 = require("@alanszp/jwt");
|
|
14
|
-
const errors_1 = require("@alanszp/errors");
|
|
15
|
-
const errorView_1 = require("../views/errorView");
|
|
16
|
-
const getRequestLogger_1 = require("../helpers/getRequestLogger");
|
|
17
|
-
function parseAuthorizationHeader(authorization) {
|
|
18
|
-
if (!authorization)
|
|
19
|
-
return undefined;
|
|
20
|
-
const [bearer, jwt, ...other] = authorization.split(" ");
|
|
21
|
-
if (bearer !== "Bearer" || other.length > 0)
|
|
22
|
-
return undefined;
|
|
23
|
-
return jwt;
|
|
24
|
-
}
|
|
25
|
-
function createAuthWithJWT(publicKey, options) {
|
|
26
|
-
return function authWithJwt(req, res, next) {
|
|
27
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
-
const logger = (0, getRequestLogger_1.getRequestLogger)(req);
|
|
29
|
-
const cookies = req.cookies || {};
|
|
30
|
-
const jwt = cookies.jwt || parseAuthorizationHeader(req.headers.authorization);
|
|
31
|
-
if (!jwt) {
|
|
32
|
-
logger.debug("auth.authWithJwt.error.notPresent", {
|
|
33
|
-
headers: req.headers,
|
|
34
|
-
});
|
|
35
|
-
res.status(401).json((0, errorView_1.errorView)(new errors_1.UnauthorizedError(["jwt"])));
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
try {
|
|
39
|
-
const jwtUser = yield (0, jwt_1.verifyJWT)(publicKey, jwt, options);
|
|
40
|
-
logger.debug("auth.authWithJwt.authed", {
|
|
41
|
-
user: jwtUser.id,
|
|
42
|
-
org: jwtUser.organizationReference,
|
|
43
|
-
});
|
|
44
|
-
req.context.jwtUser = jwtUser;
|
|
45
|
-
req.context.authenticated.push("jwt");
|
|
46
|
-
next();
|
|
47
|
-
}
|
|
48
|
-
catch (error) {
|
|
49
|
-
logger.info("auth.authWithJwt.invalidJwt", { jwt, error });
|
|
50
|
-
res.status(401).json((0, errorView_1.errorView)(new errors_1.UnauthorizedError(["jwt"])));
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
exports.createAuthWithJWT = createAuthWithJWT;
|
|
56
|
-
//# sourceMappingURL=authWithJWT.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"authWithJWT.js","sourceRoot":"","sources":["../../src/middlewares/authWithJWT.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,sCAAwD;AACxD,4CAAoD;AACpD,kDAA+C;AAE/C,kEAA+D;AAG/D,SAAS,wBAAwB,CAC/B,aAAiC;IAEjC,IAAI,CAAC,aAAa;QAAE,OAAO,SAAS,CAAC;IACrC,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAEzD,IAAI,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAE9D,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAgB,iBAAiB,CAAC,SAAiB,EAAE,OAAuB;IAC1E,OAAO,SAAe,WAAW,CAC/B,GAAmB,EACnB,GAAa,EACb,IAAkB;;YAElB,MAAM,MAAM,GAAG,IAAA,mCAAgB,EAAC,GAAG,CAAC,CAAC;YACrC,MAAM,OAAO,GAAI,GAAG,CAAC,OAA8C,IAAI,EAAE,CAAC;YAC1E,MAAM,GAAG,GACP,OAAO,CAAC,GAAG,IAAI,wBAAwB,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAErE,IAAI,CAAC,GAAG,EAAE;gBACR,MAAM,CAAC,KAAK,CAAC,mCAAmC,EAAE;oBAChD,OAAO,EAAE,GAAG,CAAC,OAAO;iBACrB,CAAC,CAAC;gBACH,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAA,qBAAS,EAAC,IAAI,0BAAiB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBAChE,OAAO;aACR;YAED,IAAI;gBACF,MAAM,OAAO,GAAG,MAAM,IAAA,eAAS,EAAC,SAAS,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;gBACzD,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE;oBACtC,IAAI,EAAE,OAAO,CAAC,EAAE;oBAChB,GAAG,EAAE,OAAO,CAAC,qBAAqB;iBACnC,CAAC,CAAC;gBAEH,GAAG,CAAC,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC;gBAC9B,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAEtC,IAAI,EAAE,CAAC;aACR;YAAC,OAAO,KAAc,EAAE;gBACvB,MAAM,CAAC,IAAI,CAAC,6BAA6B,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC3D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAA,qBAAS,EAAC,IAAI,0BAAiB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;aACjE;QACH,CAAC;KAAA,CAAC;AACJ,CAAC;AAnCD,8CAmCC"}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { verifyJWT, VerifyOptions } from "@alanszp/jwt";
|
|
2
|
-
import { UnauthorizedError } from "@alanszp/errors";
|
|
3
|
-
import { errorView } from "../views/errorView";
|
|
4
|
-
import { NextFunction, Response } from "express";
|
|
5
|
-
import { getRequestLogger } from "../helpers/getRequestLogger";
|
|
6
|
-
import { GenericRequest } from "../types/GenericRequest";
|
|
7
|
-
|
|
8
|
-
function parseAuthorizationHeader(
|
|
9
|
-
authorization: string | undefined
|
|
10
|
-
): string | undefined {
|
|
11
|
-
if (!authorization) return undefined;
|
|
12
|
-
const [bearer, jwt, ...other] = authorization.split(" ");
|
|
13
|
-
|
|
14
|
-
if (bearer !== "Bearer" || other.length > 0) return undefined;
|
|
15
|
-
|
|
16
|
-
return jwt;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function createAuthWithJWT(publicKey: string, options?: VerifyOptions) {
|
|
20
|
-
return async function authWithJwt(
|
|
21
|
-
req: GenericRequest,
|
|
22
|
-
res: Response,
|
|
23
|
-
next: NextFunction
|
|
24
|
-
): Promise<void> {
|
|
25
|
-
const logger = getRequestLogger(req);
|
|
26
|
-
const cookies = (req.cookies as Record<string, string | undefined>) || {};
|
|
27
|
-
const jwt =
|
|
28
|
-
cookies.jwt || parseAuthorizationHeader(req.headers.authorization);
|
|
29
|
-
|
|
30
|
-
if (!jwt) {
|
|
31
|
-
logger.debug("auth.authWithJwt.error.notPresent", {
|
|
32
|
-
headers: req.headers,
|
|
33
|
-
});
|
|
34
|
-
res.status(401).json(errorView(new UnauthorizedError(["jwt"])));
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
const jwtUser = await verifyJWT(publicKey, jwt, options);
|
|
40
|
-
logger.debug("auth.authWithJwt.authed", {
|
|
41
|
-
user: jwtUser.id,
|
|
42
|
-
org: jwtUser.organizationReference,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
req.context.jwtUser = jwtUser;
|
|
46
|
-
req.context.authenticated.push("jwt");
|
|
47
|
-
|
|
48
|
-
next();
|
|
49
|
-
} catch (error: unknown) {
|
|
50
|
-
logger.info("auth.authWithJwt.invalidJwt", { jwt, error });
|
|
51
|
-
res.status(401).json(errorView(new UnauthorizedError(["jwt"])));
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
}
|