@alanszp/express 6.0.4 → 7.0.1
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/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/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,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.laraJwtUserMock = exports.userJwtUserMock = void 0;
|
|
4
|
+
exports.userJwtUserMock = {
|
|
5
|
+
id: "1",
|
|
6
|
+
employeeReference: "1",
|
|
7
|
+
organizationReference: "test",
|
|
8
|
+
roles: [],
|
|
9
|
+
permissions: [],
|
|
10
|
+
};
|
|
11
|
+
exports.laraJwtUserMock = {
|
|
12
|
+
id: "0",
|
|
13
|
+
employeeReference: "0",
|
|
14
|
+
organizationReference: "lara",
|
|
15
|
+
roles: [],
|
|
16
|
+
permissions: [],
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=jwtUserMocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwtUserMocks.js","sourceRoot":"","sources":["../../../src/test/mocks/jwtUserMocks.ts"],"names":[],"mappings":";;;AAEa,QAAA,eAAe,GAAY;IACtC,EAAE,EAAE,GAAG;IACP,iBAAiB,EAAE,GAAG;IACtB,qBAAqB,EAAE,MAAM;IAC7B,KAAK,EAAE,EAAE;IACT,WAAW,EAAE,EAAE;CAChB,CAAC;AAEW,QAAA,eAAe,GAAY;IACtC,EAAE,EAAE,GAAG;IACP,iBAAiB,EAAE,GAAG;IACtB,qBAAqB,EAAE,MAAM;IAC7B,KAAK,EAAE,EAAE;IACT,WAAW,EAAE,EAAE;CAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/test/setup.ts"],"names":[],"mappings":";;AAAA,mCAAgC;AAEhC,IAAA,eAAM,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const now_1 = require("../helpers/now");
|
|
4
|
+
jest.mock("@/helpers/now");
|
|
5
|
+
describe("Timezones", () => {
|
|
6
|
+
it("should always be UTC", () => {
|
|
7
|
+
expect(new Date().getTimezoneOffset()).toBe(0);
|
|
8
|
+
});
|
|
9
|
+
it("now() is mocked", () => {
|
|
10
|
+
now_1.now.mockReturnValue(new Date("2021-01-01T12:30:43"));
|
|
11
|
+
expect((0, now_1.now)()).toEqual(new Date("2021-01-01T12:30:43"));
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=setup.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.test.js","sourceRoot":"","sources":["../../src/test/setup.test.ts"],"names":[],"mappings":";;AAAA,wCAAqC;AAErC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAE3B,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE;QACxB,SAAiB,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAEpE,MAAM,CAAC,IAAA,SAAG,GAAE,CAAC,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -6,5 +6,5 @@ declare type GenerateStringUnion<T> = Extract<{
|
|
|
6
6
|
declare type OverridableStringUnion<T extends string | number, U = {}> = GenerateStringUnion<Overwrite<Record<T, true>, U>>;
|
|
7
7
|
export interface AuthMethodsOverride {
|
|
8
8
|
}
|
|
9
|
-
export declare type AuthMethod = OverridableStringUnion<"jwt", AuthMethodsOverride>;
|
|
9
|
+
export declare type AuthMethod = OverridableStringUnion<"jwt" | "api_key", AuthMethodsOverride>;
|
|
10
10
|
export {};
|
package/jest.config.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alanszp/express",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.1",
|
|
4
4
|
"description": "Alan's express utils and middlewares.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"scripts": {
|
|
15
15
|
"compile": "rm -rf ./dist && tsc --declaration",
|
|
16
16
|
"compile-watch": "tsc -w",
|
|
17
|
+
"test": "TZ=Etc/UTC jest",
|
|
17
18
|
"build": "yarn run compile",
|
|
18
19
|
"prepack": "yarn run build",
|
|
19
20
|
"yalc-publish": "yarn run yalc publish"
|
|
@@ -24,21 +25,25 @@
|
|
|
24
25
|
"devDependencies": {
|
|
25
26
|
"@types/body-parser": "^1.19.1",
|
|
26
27
|
"@types/express": "^4.17.12",
|
|
28
|
+
"@types/jest": "^28.1.8",
|
|
27
29
|
"@types/lodash": "^4.14.170",
|
|
28
30
|
"@types/node": "^15.12.3",
|
|
31
|
+
"babel-jest": "^29.0.0",
|
|
32
|
+
"eslint-plugin-jest": "^26.8.7",
|
|
33
|
+
"jest": "^29.0.0",
|
|
29
34
|
"ts-node": "^10.0.0",
|
|
30
35
|
"tslint": "^6.1.3",
|
|
31
36
|
"typescript": "^4.3.4"
|
|
32
37
|
},
|
|
33
38
|
"dependencies": {
|
|
34
|
-
"@alanszp/audit": "^
|
|
35
|
-
"@alanszp/errors": "^
|
|
36
|
-
"@alanszp/jwt": "^
|
|
37
|
-
"@alanszp/logger": "^
|
|
38
|
-
"@alanszp/shared-context": "^
|
|
39
|
+
"@alanszp/audit": "^7.0.0",
|
|
40
|
+
"@alanszp/errors": "^7.0.0",
|
|
41
|
+
"@alanszp/jwt": "^7.0.0",
|
|
42
|
+
"@alanszp/logger": "^7.0.0",
|
|
43
|
+
"@alanszp/shared-context": "^7.0.0",
|
|
39
44
|
"body-parser": "^1.19.0",
|
|
40
45
|
"cuid": "^2.1.8",
|
|
41
46
|
"lodash": "^4.17.21"
|
|
42
47
|
},
|
|
43
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "67e6ad3d56d02ee10f45ca59f7e68bc77d574f41"
|
|
44
49
|
}
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ export * from "./middlewares/auditLog";
|
|
|
4
4
|
export * from "./middlewares/accessLogger";
|
|
5
5
|
export * from "./middlewares/authedForOrg";
|
|
6
6
|
export * from "./middlewares/createContext";
|
|
7
|
-
export * from "./middlewares/
|
|
7
|
+
export * from "./middlewares/authenticateUser";
|
|
8
8
|
export * from "./middlewares/returnInternalServerError";
|
|
9
9
|
export * from "./middlewares/returnNotFound";
|
|
10
10
|
export * from "./middlewares/jsonBodyParser";
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import { AuthMethods, createAuthContext } from "./authenticateUser";
|
|
2
|
+
import { verifyJWT } from "@alanszp/jwt";
|
|
3
|
+
import {
|
|
4
|
+
mockNext,
|
|
5
|
+
mockRequest,
|
|
6
|
+
mockResponse,
|
|
7
|
+
} from "../test/mocks/expressMocks";
|
|
8
|
+
import { laraJwtUserMock, userJwtUserMock } from "../test/mocks/jwtUserMocks";
|
|
9
|
+
import {
|
|
10
|
+
apiKeyAuthOptions,
|
|
11
|
+
bothMethodsAuthOptions,
|
|
12
|
+
jwtAuthOptions,
|
|
13
|
+
verifyOptions,
|
|
14
|
+
} from "../test/mocks/authOptionsMocks";
|
|
15
|
+
|
|
16
|
+
jest.mock("@alanszp/jwt");
|
|
17
|
+
|
|
18
|
+
describe("AuthenticateUser", () => {
|
|
19
|
+
describe("authentication with only JWT", () => {
|
|
20
|
+
describe("when jwt verifies correctly", () => {
|
|
21
|
+
it("should authenticate correctly and call next", async () => {
|
|
22
|
+
(verifyJWT as jest.Mock).mockResolvedValueOnce(userJwtUserMock);
|
|
23
|
+
|
|
24
|
+
const req = mockRequest("Bearer token");
|
|
25
|
+
const res = mockResponse();
|
|
26
|
+
const next = mockNext();
|
|
27
|
+
|
|
28
|
+
await createAuthContext(jwtAuthOptions)([AuthMethods.JWT])(
|
|
29
|
+
req,
|
|
30
|
+
res,
|
|
31
|
+
next
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
expect(verifyJWT).toBeCalledWith("publicKey", "token", verifyOptions);
|
|
35
|
+
expect(res.status).toHaveBeenCalledTimes(0);
|
|
36
|
+
expect(res.json).toHaveBeenCalledTimes(0);
|
|
37
|
+
expect(req.context.jwtUser).toMatchObject(userJwtUserMock);
|
|
38
|
+
expect(req.context.authenticated).toStrictEqual(["jwt"]);
|
|
39
|
+
expect(next).toBeCalledWith();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe("when jwt verifies incorrectly", () => {
|
|
44
|
+
it("should not authenticate, should not call next, and it should return 401", async () => {
|
|
45
|
+
(verifyJWT as jest.Mock).mockResolvedValueOnce(undefined);
|
|
46
|
+
|
|
47
|
+
const req = mockRequest("Bearer token");
|
|
48
|
+
const res = mockResponse();
|
|
49
|
+
const next = mockNext();
|
|
50
|
+
|
|
51
|
+
await createAuthContext(jwtAuthOptions)([AuthMethods.JWT])(
|
|
52
|
+
req,
|
|
53
|
+
res,
|
|
54
|
+
next
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
expect(verifyJWT).toBeCalledWith("publicKey", "token", verifyOptions);
|
|
58
|
+
expect(res.status).toHaveBeenCalledWith(401);
|
|
59
|
+
expect(res.json).toHaveBeenCalledTimes(1);
|
|
60
|
+
expect(req.context.jwtUser).toBe(undefined);
|
|
61
|
+
expect(req.context.authenticated).toEqual([]);
|
|
62
|
+
expect(next).toHaveBeenCalledTimes(0);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe("when jwt doesn't exist", () => {
|
|
67
|
+
it("should not verify JWT, should not authenticate, should not call next, and it should return 401", async () => {
|
|
68
|
+
const req = mockRequest("aa");
|
|
69
|
+
const res = mockResponse();
|
|
70
|
+
const next = mockNext();
|
|
71
|
+
|
|
72
|
+
await createAuthContext(jwtAuthOptions)([AuthMethods.JWT])(
|
|
73
|
+
req,
|
|
74
|
+
res,
|
|
75
|
+
next
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
expect(verifyJWT).toHaveBeenCalledTimes(0);
|
|
79
|
+
expect(res.status).toHaveBeenCalledWith(401);
|
|
80
|
+
expect(res.json).toHaveBeenCalledTimes(1);
|
|
81
|
+
expect(req.context.jwtUser).toBe(undefined);
|
|
82
|
+
expect(req.context.authenticated).toEqual([]);
|
|
83
|
+
expect(next).toHaveBeenCalledTimes(0);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe("authentication with only API KEY", () => {
|
|
89
|
+
describe("when api key verifies correctly", () => {
|
|
90
|
+
it("should authenticate correctly and call next", async () => {
|
|
91
|
+
const req = mockRequest("token");
|
|
92
|
+
const res = mockResponse();
|
|
93
|
+
const next = mockNext();
|
|
94
|
+
|
|
95
|
+
await createAuthContext(apiKeyAuthOptions)([AuthMethods.API_KEY])(
|
|
96
|
+
req,
|
|
97
|
+
res,
|
|
98
|
+
next
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
expect(verifyJWT).toHaveBeenCalledTimes(0);
|
|
102
|
+
expect(res.status).toHaveBeenCalledTimes(0);
|
|
103
|
+
expect(res.json).toHaveBeenCalledTimes(0);
|
|
104
|
+
expect(req.context.jwtUser).toMatchObject(laraJwtUserMock);
|
|
105
|
+
expect(req.context.authenticated).toStrictEqual(["api_key"]);
|
|
106
|
+
expect(next).toBeCalledWith();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe("when api key verifies incorrectly", () => {
|
|
111
|
+
it("should not authenticate, should not call next, and it should return 401", async () => {
|
|
112
|
+
const req = mockRequest("invalidToken");
|
|
113
|
+
const res = mockResponse();
|
|
114
|
+
const next = mockNext();
|
|
115
|
+
|
|
116
|
+
await createAuthContext(apiKeyAuthOptions)([AuthMethods.API_KEY])(
|
|
117
|
+
req,
|
|
118
|
+
res,
|
|
119
|
+
next
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
expect(verifyJWT).toHaveBeenCalledTimes(0);
|
|
123
|
+
expect(res.status).toHaveBeenCalledWith(401);
|
|
124
|
+
expect(res.json).toHaveBeenCalledTimes(1);
|
|
125
|
+
expect(req.context.jwtUser).toBe(undefined);
|
|
126
|
+
expect(req.context.authenticated).toEqual([]);
|
|
127
|
+
expect(next).toHaveBeenCalledTimes(0);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe("when api key doesn't exist", () => {
|
|
132
|
+
it("should not verify api key, should not authenticate, should not call next, and it should return 401", async () => {
|
|
133
|
+
const req = mockRequest(undefined as any);
|
|
134
|
+
const res = mockResponse();
|
|
135
|
+
const next = mockNext();
|
|
136
|
+
|
|
137
|
+
await createAuthContext(apiKeyAuthOptions)([AuthMethods.API_KEY])(
|
|
138
|
+
req,
|
|
139
|
+
res,
|
|
140
|
+
next
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
expect(verifyJWT).toHaveBeenCalledTimes(0);
|
|
144
|
+
expect(res.status).toHaveBeenCalledWith(401);
|
|
145
|
+
expect(res.json).toHaveBeenCalledTimes(1);
|
|
146
|
+
expect(req.context.jwtUser).toBe(undefined);
|
|
147
|
+
expect(req.context.authenticated).toEqual([]);
|
|
148
|
+
expect(next).toHaveBeenCalledTimes(0);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe("authentication with JWT and API KEY", () => {
|
|
154
|
+
describe("using both methods", () => {
|
|
155
|
+
describe("when api key verifies correctly", () => {
|
|
156
|
+
it("should authenticate correctly and call next", async () => {
|
|
157
|
+
const req = mockRequest("token");
|
|
158
|
+
const res = mockResponse();
|
|
159
|
+
const next = mockNext();
|
|
160
|
+
|
|
161
|
+
await createAuthContext(bothMethodsAuthOptions)([
|
|
162
|
+
AuthMethods.API_KEY,
|
|
163
|
+
AuthMethods.JWT,
|
|
164
|
+
])(req, res, next);
|
|
165
|
+
|
|
166
|
+
expect(verifyJWT).toHaveBeenCalledTimes(0);
|
|
167
|
+
expect(res.status).toHaveBeenCalledTimes(0);
|
|
168
|
+
expect(res.json).toHaveBeenCalledTimes(0);
|
|
169
|
+
expect(req.context.jwtUser).toMatchObject(laraJwtUserMock);
|
|
170
|
+
expect(req.context.authenticated).toStrictEqual(["api_key"]);
|
|
171
|
+
expect(next).toHaveBeenCalledWith();
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
describe("when api key verifies incorrectly", () => {
|
|
176
|
+
it("should not authenticate, should not call next, and it should return 401", async () => {
|
|
177
|
+
const req = mockRequest("invalidToken");
|
|
178
|
+
const res = mockResponse();
|
|
179
|
+
const next = mockNext();
|
|
180
|
+
|
|
181
|
+
await createAuthContext(bothMethodsAuthOptions)([
|
|
182
|
+
AuthMethods.API_KEY,
|
|
183
|
+
AuthMethods.JWT,
|
|
184
|
+
])(req, res, next);
|
|
185
|
+
|
|
186
|
+
expect(verifyJWT).toHaveBeenCalledTimes(0);
|
|
187
|
+
expect(res.status).toHaveBeenCalledWith(401);
|
|
188
|
+
expect(res.json).toHaveBeenCalledTimes(1);
|
|
189
|
+
expect(req.context.jwtUser).toBe(undefined);
|
|
190
|
+
expect(req.context.authenticated).toEqual([]);
|
|
191
|
+
expect(next).toHaveBeenCalledTimes(0);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
describe("when jwt verifies correctly", () => {
|
|
196
|
+
it("should authenticate correctly and call next", async () => {
|
|
197
|
+
(verifyJWT as jest.Mock).mockResolvedValueOnce(userJwtUserMock);
|
|
198
|
+
|
|
199
|
+
const req = mockRequest("Bearer token");
|
|
200
|
+
const res = mockResponse();
|
|
201
|
+
const next = mockNext();
|
|
202
|
+
|
|
203
|
+
await createAuthContext(bothMethodsAuthOptions)([
|
|
204
|
+
AuthMethods.API_KEY,
|
|
205
|
+
AuthMethods.JWT,
|
|
206
|
+
])(req, res, next);
|
|
207
|
+
|
|
208
|
+
expect(verifyJWT).toBeCalledWith("publicKey", "token", {
|
|
209
|
+
issuer: "issuer",
|
|
210
|
+
audience: "audience",
|
|
211
|
+
});
|
|
212
|
+
expect(res.status).toHaveBeenCalledTimes(0);
|
|
213
|
+
expect(res.json).toHaveBeenCalledTimes(0);
|
|
214
|
+
|
|
215
|
+
expect(req.context.jwtUser).toMatchObject(userJwtUserMock);
|
|
216
|
+
|
|
217
|
+
expect(req.context.authenticated).toStrictEqual(["jwt"]);
|
|
218
|
+
|
|
219
|
+
expect(next).toHaveBeenCalledWith();
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
describe("when jwt verifies incorrectly", () => {
|
|
224
|
+
it("should not authenticate, should not call next, and it should return 401", async () => {
|
|
225
|
+
(verifyJWT as jest.Mock).mockResolvedValueOnce(undefined);
|
|
226
|
+
|
|
227
|
+
const req = mockRequest("Bearer token");
|
|
228
|
+
const res = mockResponse();
|
|
229
|
+
const next = mockNext();
|
|
230
|
+
|
|
231
|
+
await createAuthContext(bothMethodsAuthOptions)([
|
|
232
|
+
AuthMethods.API_KEY,
|
|
233
|
+
AuthMethods.JWT,
|
|
234
|
+
])(req, res, next);
|
|
235
|
+
|
|
236
|
+
expect(verifyJWT).toBeCalledWith("publicKey", "token", {
|
|
237
|
+
issuer: "issuer",
|
|
238
|
+
audience: "audience",
|
|
239
|
+
});
|
|
240
|
+
expect(res.status).toHaveBeenCalledWith(401);
|
|
241
|
+
expect(res.json).toHaveBeenCalledTimes(1);
|
|
242
|
+
expect(req.context.jwtUser).toBe(undefined);
|
|
243
|
+
expect(req.context.authenticated).toEqual([]);
|
|
244
|
+
expect(next).toHaveBeenCalledTimes(0);
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
describe("when jwt doesnt exist", () => {
|
|
249
|
+
it("should not authenticate, should not call next, and it should return 401", async () => {
|
|
250
|
+
const req = mockRequest(undefined as any);
|
|
251
|
+
const res = mockResponse();
|
|
252
|
+
const next = mockNext();
|
|
253
|
+
|
|
254
|
+
await createAuthContext(bothMethodsAuthOptions)([
|
|
255
|
+
AuthMethods.API_KEY,
|
|
256
|
+
AuthMethods.JWT,
|
|
257
|
+
])(req, res, next);
|
|
258
|
+
|
|
259
|
+
expect(verifyJWT).toHaveBeenCalledTimes(0);
|
|
260
|
+
expect(res.status).toHaveBeenCalledWith(401);
|
|
261
|
+
expect(res.json).toHaveBeenCalledTimes(1);
|
|
262
|
+
expect(req.context.jwtUser).toBe(undefined);
|
|
263
|
+
expect(req.context.authenticated).toEqual([]);
|
|
264
|
+
expect(next).toHaveBeenCalledTimes(0);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
describe("using jwt method", () => {
|
|
270
|
+
describe("when jwt verifies correctly", () => {
|
|
271
|
+
it("should authenticate correctly and call next", async () => {
|
|
272
|
+
(verifyJWT as jest.Mock).mockResolvedValueOnce(userJwtUserMock);
|
|
273
|
+
|
|
274
|
+
const req = mockRequest("Bearer token");
|
|
275
|
+
const res = mockResponse();
|
|
276
|
+
const next = mockNext();
|
|
277
|
+
|
|
278
|
+
await createAuthContext(bothMethodsAuthOptions)([AuthMethods.JWT])(
|
|
279
|
+
req,
|
|
280
|
+
res,
|
|
281
|
+
next
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
expect(verifyJWT).toBeCalledWith("publicKey", "token", {
|
|
285
|
+
issuer: "issuer",
|
|
286
|
+
audience: "audience",
|
|
287
|
+
});
|
|
288
|
+
expect(res.status).toHaveBeenCalledTimes(0);
|
|
289
|
+
expect(res.json).toHaveBeenCalledTimes(0);
|
|
290
|
+
expect(req.context.jwtUser).toMatchObject(userJwtUserMock);
|
|
291
|
+
expect(req.context.authenticated).toStrictEqual(["jwt"]);
|
|
292
|
+
expect(next).toHaveBeenCalledWith();
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
describe("when jwt verifies incorrectly", () => {
|
|
297
|
+
it("should not authenticate, should not call next, and it should return 401", async () => {
|
|
298
|
+
(verifyJWT as jest.Mock).mockResolvedValueOnce(undefined);
|
|
299
|
+
|
|
300
|
+
const req = mockRequest("Bearer invalidToken");
|
|
301
|
+
const res = mockResponse();
|
|
302
|
+
const next = mockNext();
|
|
303
|
+
|
|
304
|
+
await createAuthContext(bothMethodsAuthOptions)([AuthMethods.JWT])(
|
|
305
|
+
req,
|
|
306
|
+
res,
|
|
307
|
+
next
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
expect(verifyJWT).toBeCalledWith("publicKey", "invalidToken", {
|
|
311
|
+
issuer: "issuer",
|
|
312
|
+
audience: "audience",
|
|
313
|
+
});
|
|
314
|
+
expect(res.status).toHaveBeenCalledWith(401);
|
|
315
|
+
expect(res.json).toHaveBeenCalledTimes(1);
|
|
316
|
+
expect(req.context.jwtUser).toBe(undefined);
|
|
317
|
+
expect(req.context.authenticated).toEqual([]);
|
|
318
|
+
expect(next).toHaveBeenCalledTimes(0);
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
describe("when api key verifies correctly", () => {
|
|
323
|
+
it("should authenticate correctly and call next", async () => {
|
|
324
|
+
const req = mockRequest("token");
|
|
325
|
+
const res = mockResponse();
|
|
326
|
+
const next = mockNext();
|
|
327
|
+
|
|
328
|
+
await createAuthContext(bothMethodsAuthOptions)([
|
|
329
|
+
AuthMethods.API_KEY,
|
|
330
|
+
])(req, res, next);
|
|
331
|
+
|
|
332
|
+
expect(verifyJWT).toHaveBeenCalledTimes(0);
|
|
333
|
+
expect(res.status).toHaveBeenCalledTimes(0);
|
|
334
|
+
expect(res.json).toHaveBeenCalledTimes(0);
|
|
335
|
+
|
|
336
|
+
expect(req.context.jwtUser).toMatchObject(laraJwtUserMock);
|
|
337
|
+
expect(req.context.authenticated).toStrictEqual(["api_key"]);
|
|
338
|
+
expect(next).toHaveBeenCalledWith();
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
describe("when api key verifies incorrectly", () => {
|
|
343
|
+
it("should not authenticate, should not call next, and it should return 401", async () => {
|
|
344
|
+
const req = mockRequest("invalidToken");
|
|
345
|
+
const res = mockResponse();
|
|
346
|
+
const next = mockNext();
|
|
347
|
+
|
|
348
|
+
await createAuthContext(bothMethodsAuthOptions)([
|
|
349
|
+
AuthMethods.API_KEY,
|
|
350
|
+
AuthMethods.JWT,
|
|
351
|
+
])(req, res, next);
|
|
352
|
+
|
|
353
|
+
expect(verifyJWT).toHaveBeenCalledTimes(0);
|
|
354
|
+
expect(res.status).toHaveBeenCalledWith(401);
|
|
355
|
+
expect(res.json).toHaveBeenCalledTimes(1);
|
|
356
|
+
expect(req.context.jwtUser).toBe(undefined);
|
|
357
|
+
expect(req.context.authenticated).toEqual([]);
|
|
358
|
+
expect(next).toHaveBeenCalledTimes(0);
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
describe("when jwt doesnt exist", () => {
|
|
363
|
+
it("should not authenticate, should not call next, and it should return 401", async () => {
|
|
364
|
+
const req = mockRequest("aaa");
|
|
365
|
+
const res = mockResponse();
|
|
366
|
+
const next = mockNext();
|
|
367
|
+
|
|
368
|
+
await createAuthContext(bothMethodsAuthOptions)([AuthMethods.JWT])(
|
|
369
|
+
req,
|
|
370
|
+
res,
|
|
371
|
+
next
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
expect(verifyJWT).toHaveBeenCalledTimes(0);
|
|
375
|
+
expect(res.status).toHaveBeenCalledWith(401);
|
|
376
|
+
expect(res.json).toHaveBeenCalledTimes(1);
|
|
377
|
+
expect(req.context.jwtUser).toBe(undefined);
|
|
378
|
+
expect(req.context.authenticated).toEqual([]);
|
|
379
|
+
expect(next).toHaveBeenCalledTimes(0);
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
describe("when api key doesnt exist", () => {
|
|
384
|
+
it("should not authenticate, should not call next, and it should return 401", async () => {
|
|
385
|
+
const req = mockRequest(undefined as any);
|
|
386
|
+
const res = mockResponse();
|
|
387
|
+
const next = mockNext();
|
|
388
|
+
|
|
389
|
+
await createAuthContext(bothMethodsAuthOptions)([
|
|
390
|
+
AuthMethods.API_KEY,
|
|
391
|
+
])(req, res, next);
|
|
392
|
+
|
|
393
|
+
expect(verifyJWT).toHaveBeenCalledTimes(0);
|
|
394
|
+
expect(res.status).toHaveBeenCalledWith(401);
|
|
395
|
+
expect(res.json).toHaveBeenCalledTimes(1);
|
|
396
|
+
expect(req.context.jwtUser).toBe(undefined);
|
|
397
|
+
expect(req.context.authenticated).toEqual([]);
|
|
398
|
+
expect(next).toHaveBeenCalledTimes(0);
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
});
|
|
403
|
+
});
|