node-server-engine 1.1.6 → 1.1.8
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.example +0 -38
- package/.nycrc +9 -3
- package/README.md +2 -3
- package/dist/const/tokenIssuer.d.ts +2 -4
- package/dist/const/tokenIssuer.js +0 -1
- package/dist/const/tokenIssuer.js.map +1 -1
- package/dist/entities/Endpoint/Endpoint.types.d.ts +2 -19
- package/dist/entities/Endpoint/Endpoint.types.js +1 -8
- package/dist/entities/Endpoint/Endpoint.types.js.map +1 -1
- package/dist/entities/Server/Server.js +5 -0
- package/dist/entities/Server/Server.js.map +1 -1
- package/dist/middleware/index.d.ts +0 -1
- package/dist/middleware/index.js +0 -11
- package/dist/middleware/index.js.map +1 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -11
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/jwt/jwt.d.ts +0 -1
- package/dist/utils/jwt/jwt.js +2 -23
- package/dist/utils/jwt/jwt.js.map +1 -1
- package/dist/utils/report/report.js +1 -2
- package/dist/utils/report/report.js.map +1 -1
- package/package.json +9 -7
- package/src/const/tokenIssuer.ts +1 -3
- package/src/entities/Endpoint/Endpoint.test.ts +0 -89
- package/src/entities/Endpoint/Endpoint.types.ts +3 -30
- package/src/entities/KeySet/KeySet.test.ts +1 -1
- package/src/entities/Server/Server.ts +9 -0
- package/src/middleware/index.ts +0 -1
- package/src/utils/index.ts +0 -1
- package/src/utils/jwt/jwt.test.ts +0 -13
- package/src/utils/jwt/jwt.ts +2 -25
- package/src/utils/report/report.ts +1 -2
- package/test/env.ts +0 -5
- package/test/hooks.ts +0 -2
- package/dist/middleware/authAdmin/authAdmin.d.ts +0 -4
- package/dist/middleware/authAdmin/authAdmin.js +0 -105
- package/dist/middleware/authAdmin/authAdmin.js.map +0 -1
- package/dist/middleware/authAdmin/authAdmin.types.d.ts +0 -16
- package/dist/middleware/authAdmin/authAdmin.types.js +0 -2
- package/dist/middleware/authAdmin/authAdmin.types.js.map +0 -1
- package/dist/middleware/authAdmin/index.d.ts +0 -2
- package/dist/middleware/authAdmin/index.js +0 -28
- package/dist/middleware/authAdmin/index.js.map +0 -1
- package/dist/utils/getDynamicLink/getDynamicLink.d.ts +0 -3
- package/dist/utils/getDynamicLink/getDynamicLink.js +0 -28
- package/dist/utils/getDynamicLink/getDynamicLink.js.map +0 -1
- package/dist/utils/getDynamicLink/getDynamicLink.types.d.ts +0 -10
- package/dist/utils/getDynamicLink/getDynamicLink.types.js +0 -2
- package/dist/utils/getDynamicLink/getDynamicLink.types.js.map +0 -1
- package/dist/utils/getDynamicLink/getDynamicLink.validate.d.ts +0 -2
- package/dist/utils/getDynamicLink/getDynamicLink.validate.js +0 -14
- package/dist/utils/getDynamicLink/getDynamicLink.validate.js.map +0 -1
- package/dist/utils/getDynamicLink/index.d.ts +0 -2
- package/dist/utils/getDynamicLink/index.js +0 -28
- package/dist/utils/getDynamicLink/index.js.map +0 -1
- package/src/middleware/authAdmin/authAdmin.test.ts +0 -199
- package/src/middleware/authAdmin/authAdmin.ts +0 -114
- package/src/middleware/authAdmin/authAdmin.types.ts +0 -19
- package/src/middleware/authAdmin/index.ts +0 -2
- package/src/utils/getDynamicLink/getDynamicLink.test.ts +0 -51
- package/src/utils/getDynamicLink/getDynamicLink.ts +0 -28
- package/src/utils/getDynamicLink/getDynamicLink.types.ts +0 -11
- package/src/utils/getDynamicLink/getDynamicLink.validate.ts +0 -6
- package/src/utils/getDynamicLink/index.ts +0 -2
package/dist/utils/jwt/jwt.js
CHANGED
|
@@ -4,7 +4,6 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.adminKeySet = void 0;
|
|
8
7
|
exports.generateJwtToken = generateJwtToken;
|
|
9
8
|
exports.initKeySets = initKeySets;
|
|
10
9
|
exports.jwtVerify = jwtVerify;
|
|
@@ -20,7 +19,6 @@ var _checkEnvironment = require("../checkEnvironment");
|
|
|
20
19
|
var _envAssert = require("../envAssert");
|
|
21
20
|
var _report = require("../report");
|
|
22
21
|
let keySet = exports.keySet = void 0;
|
|
23
|
-
let adminKeySet = exports.adminKeySet = void 0;
|
|
24
22
|
const namespace = 'engine:utils:jwt';
|
|
25
23
|
|
|
26
24
|
/** Initiate key fetching mechanism */
|
|
@@ -47,22 +45,12 @@ async function initKeySets() {
|
|
|
47
45
|
});
|
|
48
46
|
}
|
|
49
47
|
const promise = [keySet.init.bind(keySet)()];
|
|
50
|
-
|
|
51
|
-
// Load the key set for the admin api
|
|
52
|
-
if (!process.env.ADMIN_API_ECDSA_PUBLIC_KEY) throw new _EngineError.EngineError({
|
|
53
|
-
message: "Admin API's authentication JWT signing public key is not defined"
|
|
54
|
-
});
|
|
55
|
-
exports.adminKeySet = adminKeySet = new _KeySet.KeySet(process.env.ADMIN_API_ECDSA_PUBLIC_KEY, {
|
|
56
|
-
pem: true
|
|
57
|
-
});
|
|
58
|
-
promise.push(adminKeySet.init.bind(adminKeySet)());
|
|
59
48
|
await Promise.all(promise);
|
|
60
49
|
}
|
|
61
50
|
|
|
62
51
|
/** Stop fetching keys regularly */
|
|
63
52
|
function shutdownKeySets() {
|
|
64
53
|
if (keySet) keySet.shutdown.bind(keySet)();
|
|
65
|
-
if (adminKeySet) adminKeySet.shutdown.bind(adminKeySet)();
|
|
66
54
|
}
|
|
67
55
|
|
|
68
56
|
/** Get the JWT public key */
|
|
@@ -73,7 +61,7 @@ function jwtGetKey(header, callback) {
|
|
|
73
61
|
return;
|
|
74
62
|
}
|
|
75
63
|
// Check that KeySet has been initialized
|
|
76
|
-
if (!keySet
|
|
64
|
+
if (!keySet) {
|
|
77
65
|
callback(new _EngineError.EngineError({
|
|
78
66
|
message: 'KeySet has not been initialized'
|
|
79
67
|
}));
|
|
@@ -134,9 +122,7 @@ async function jwtVerify(token, issuer = _const.TokenIssuer.AUTH_SERVICE) {
|
|
|
134
122
|
}
|
|
135
123
|
(0, _checkEnvironment.assertEnvironment)({
|
|
136
124
|
ACCESS_TOKEN_AUDIENCE: _envAssert.envAssert.isString(),
|
|
137
|
-
ACCESS_TOKEN_ISSUER: _envAssert.envAssert.isString()
|
|
138
|
-
ADMIN_API_ACCESS_TOKEN_AUDIENCE: _envAssert.envAssert.isString(),
|
|
139
|
-
ADMIN_ACCESS_TOKEN_ISSUER: _envAssert.envAssert.isString()
|
|
125
|
+
ACCESS_TOKEN_ISSUER: _envAssert.envAssert.isString()
|
|
140
126
|
});
|
|
141
127
|
let options;
|
|
142
128
|
switch (issuer) {
|
|
@@ -147,13 +133,6 @@ async function jwtVerify(token, issuer = _const.TokenIssuer.AUTH_SERVICE) {
|
|
|
147
133
|
algorithms
|
|
148
134
|
};
|
|
149
135
|
break;
|
|
150
|
-
case _const.TokenIssuer.ADMIN_API:
|
|
151
|
-
options = {
|
|
152
|
-
audience: [process.env.ADMIN_API_ACCESS_TOKEN_AUDIENCE],
|
|
153
|
-
issuer: [process.env.ADMIN_ACCESS_TOKEN_ISSUER],
|
|
154
|
-
algorithms
|
|
155
|
-
};
|
|
156
|
-
break;
|
|
157
136
|
default:
|
|
158
137
|
throw new _EngineError.EngineError({
|
|
159
138
|
message: `Invalid token issuer specified "${issuer}"`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.js","names":["_jsonwebtoken","require","_fs","_interopRequireDefault","_const","_EngineError","_KeySet","_WebError","_checkEnvironment","_envAssert","_report","keySet","exports","adminKeySet","namespace","initKeySets","process","env","CHART","ECDSA_PUBLIC_KEY","EngineError","message","KeySet","file","AUTH_SERVICE_URL","internal","promise","init","bind","ADMIN_API_ECDSA_PUBLIC_KEY","pem","push","Promise","all","shutdownKeySets","shutdown","jwtGetKey","header","callback","NODE_ENV","JWT_SECRET","kid","data","reportDebug","key","getKey","error","Error","WebError","statusCode","errorCode","jwtVerify","token","issuer","TokenIssuer","AUTH_SERVICE","algorithms","assertEnvironment","envAssert","isString","ACCESS_TOKEN_AUDIENCE","ACCESS_TOKEN_ISSUER","ADMIN_API_ACCESS_TOKEN_AUDIENCE","ADMIN_ACCESS_TOKEN_ISSUER","options","audience","ADMIN_API","resolve","reject","verify","result","undefined","generateJwtToken","user","signOptions","algorithm","expiresIn","keyid","Object","keys","getKeys","privateKey","fs","readFileSync","PRIVATE_KEY_PATH","sign"],"sources":["../../../src/utils/jwt/jwt.ts"],"sourcesContent":["import {\n verify,\n JwtHeader,\n SigningKeyCallback,\n Algorithm,\n VerifyOptions,\n sign\n} from 'jsonwebtoken';\nimport fs from 'fs';\nimport path from 'path';\nimport { UserTokenPayload } from './jwt.types';\nimport { TokenIssuer } from 'const';\nimport { EngineError } from 'entities/EngineError';\nimport { KeySet } from 'entities/KeySet';\nimport { WebError } from 'entities/WebError';\nimport { assertEnvironment } from 'utils/checkEnvironment';\nimport { envAssert } from 'utils/envAssert';\nimport { reportDebug } from 'utils/report';\n\nexport let keySet: KeySet | undefined;\nexport let adminKeySet: KeySet | undefined;\n\nconst namespace = 'engine:utils:jwt';\n\n/** Initiate key fetching mechanism */\nexport async function initKeySets(): Promise<void> {\n // Create the KeySet instance\n // The auth-service fetches its key from its disk and not from a network request\n // This prevents fetch failures the first time the auth-service is started\n if (process.env.CHART === 'auth-service') {\n if (!process.env.ECDSA_PUBLIC_KEY)\n throw new EngineError({\n message: 'Environment variable \"ECDSA_PUBLIC_KEY\" is not defined'\n });\n keySet = new KeySet(process.env.ECDSA_PUBLIC_KEY, { file: true });\n } else {\n if (process.env.AUTH_SERVICE_URL)\n keySet = new KeySet(\n `${process.env.AUTH_SERVICE_URL}/.well-known/jwks.json`,\n { internal: true }\n );\n else\n keySet = new KeySet(`./keys/jwks.json`, { internal: true, file: true });\n\n if (!keySet)\n throw new EngineError({\n message:\n 'Environment variable \"AUTH_SERVICE_URL\" is not defined or JWKS not found'\n });\n }\n const promise = [keySet.init.bind(keySet)()];\n\n // Load the key set for the admin api\n if (!process.env.ADMIN_API_ECDSA_PUBLIC_KEY)\n throw new EngineError({\n message:\n \"Admin API's authentication JWT signing public key is not defined\"\n });\n adminKeySet = new KeySet(process.env.ADMIN_API_ECDSA_PUBLIC_KEY, {\n pem: true\n });\n promise.push(adminKeySet.init.bind(adminKeySet)());\n\n await Promise.all(promise);\n}\n\n/** Stop fetching keys regularly */\nexport function shutdownKeySets(): void {\n if (keySet) keySet.shutdown.bind(keySet)();\n if (adminKeySet) adminKeySet.shutdown.bind(adminKeySet)();\n}\n\n/** Get the JWT public key */\nfunction jwtGetKey(header: JwtHeader, callback: SigningKeyCallback): void {\n // In test environment we return the symmetric signature secret\n if (process.env.NODE_ENV === 'test') {\n callback(null, process.env.JWT_SECRET);\n return;\n }\n // Check that KeySet has been initialized\n if (!keySet || !adminKeySet) {\n callback(new EngineError({ message: 'KeySet has not been initialized' }));\n return;\n }\n // Check that the token has a key ID\n if (!header.kid) {\n callback(\n new EngineError({\n message:\n 'Token has not key ID in header, impossible to match with known key',\n data: header\n })\n );\n return;\n }\n\n // In test environment we use a symmetrical secret bases signature\n if (process.env.NODE_ENV === 'test') {\n callback(null, process.env.JWT_SECRET);\n return;\n }\n reportDebug({\n namespace,\n message: `Looking for key with ID \"${header.kid}\"`\n });\n // Go through each key set to check if the token's key is in one of them\n let key;\n try {\n key = keySet.getKey(header.kid);\n } catch (error: Error | null | unknown) {\n callback(error instanceof Error ? error : null);\n return;\n }\n\n if (key) {\n reportDebug({ namespace, message: `Found key with ID \"${header.kid}\"` });\n callback(null, key);\n return;\n }\n callback(\n new WebError({\n statusCode: 401,\n errorCode: 'unauthorized',\n message: 'Could not find the tokens key in any key set',\n data: { kid: header.kid }\n })\n );\n}\n\n/** Verify an user Json Web Token */\nexport async function jwtVerify(\n token: string,\n issuer: TokenIssuer = TokenIssuer.AUTH_SERVICE\n): Promise<UserTokenPayload> {\n let algorithms = ['ES256' as Algorithm];\n if (process.env.NODE_ENV === 'test') {\n assertEnvironment({ JWT_SECRET: envAssert.isString() });\n algorithms = ['HS256' as Algorithm];\n }\n assertEnvironment({\n ACCESS_TOKEN_AUDIENCE: envAssert.isString(),\n ACCESS_TOKEN_ISSUER: envAssert.isString(),\n ADMIN_API_ACCESS_TOKEN_AUDIENCE: envAssert.isString(),\n ADMIN_ACCESS_TOKEN_ISSUER: envAssert.isString()\n });\n let options: VerifyOptions | undefined;\n\n switch (issuer) {\n case TokenIssuer.AUTH_SERVICE:\n options = {\n audience: [process.env.ACCESS_TOKEN_AUDIENCE as string],\n issuer: [process.env.ACCESS_TOKEN_ISSUER as string],\n algorithms\n };\n break;\n case TokenIssuer.ADMIN_API:\n options = {\n audience: [process.env.ADMIN_API_ACCESS_TOKEN_AUDIENCE as string],\n issuer: [process.env.ADMIN_ACCESS_TOKEN_ISSUER as string],\n algorithms\n };\n break;\n default:\n throw new EngineError({\n message: `Invalid token issuer specified \"${issuer as string}\"`\n });\n }\n\n return new Promise<UserTokenPayload>((resolve, reject) => {\n verify(token, jwtGetKey, options, (error, result) => {\n if (error) {\n reject(\n new WebError({\n errorCode: 'unauthorized',\n statusCode: 401,\n message: 'Invalid token supplied',\n data: { token },\n error: error instanceof Error ? error : undefined\n })\n );\n return;\n }\n resolve(result as UserTokenPayload);\n });\n });\n}\n\nexport function generateJwtToken(user: unknown) {\n const signOptions = {\n algorithm: 'ES256' as const, // or 'ES256' as Algorithm\n expiresIn: '1h',\n issuer: process.env.ACCESS_TOKEN_ISSUER,\n audience: process.env.ACCESS_TOKEN_AUDIENCE,\n keyid: Object.keys(keySet?.getKeys() ?? {})[0]\n };\n\n const privateKey = fs.readFileSync(\n process.env.PRIVATE_KEY_PATH ?? 'keys/private-key.pem',\n 'utf8'\n );\n const token = sign({ user }, privateKey, signOptions);\n\n return token;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"jwt.js","names":["_jsonwebtoken","require","_fs","_interopRequireDefault","_const","_EngineError","_KeySet","_WebError","_checkEnvironment","_envAssert","_report","keySet","exports","namespace","initKeySets","process","env","CHART","ECDSA_PUBLIC_KEY","EngineError","message","KeySet","file","AUTH_SERVICE_URL","internal","promise","init","bind","Promise","all","shutdownKeySets","shutdown","jwtGetKey","header","callback","NODE_ENV","JWT_SECRET","kid","data","reportDebug","key","getKey","error","Error","WebError","statusCode","errorCode","jwtVerify","token","issuer","TokenIssuer","AUTH_SERVICE","algorithms","assertEnvironment","envAssert","isString","ACCESS_TOKEN_AUDIENCE","ACCESS_TOKEN_ISSUER","options","audience","resolve","reject","verify","result","undefined","generateJwtToken","user","signOptions","algorithm","expiresIn","keyid","Object","keys","getKeys","privateKey","fs","readFileSync","PRIVATE_KEY_PATH","sign"],"sources":["../../../src/utils/jwt/jwt.ts"],"sourcesContent":["import {\n verify,\n JwtHeader,\n SigningKeyCallback,\n Algorithm,\n VerifyOptions,\n sign\n} from 'jsonwebtoken';\nimport fs from 'fs';\nimport { UserTokenPayload } from './jwt.types';\nimport { TokenIssuer } from 'const';\nimport { EngineError } from 'entities/EngineError';\nimport { KeySet } from 'entities/KeySet';\nimport { WebError } from 'entities/WebError';\nimport { assertEnvironment } from 'utils/checkEnvironment';\nimport { envAssert } from 'utils/envAssert';\nimport { reportDebug } from 'utils/report';\n\nexport let keySet: KeySet | undefined;\n\nconst namespace = 'engine:utils:jwt';\n\n/** Initiate key fetching mechanism */\nexport async function initKeySets(): Promise<void> {\n // Create the KeySet instance\n // The auth-service fetches its key from its disk and not from a network request\n // This prevents fetch failures the first time the auth-service is started\n if (process.env.CHART === 'auth-service') {\n if (!process.env.ECDSA_PUBLIC_KEY)\n throw new EngineError({\n message: 'Environment variable \"ECDSA_PUBLIC_KEY\" is not defined'\n });\n keySet = new KeySet(process.env.ECDSA_PUBLIC_KEY, { file: true });\n } else {\n if (process.env.AUTH_SERVICE_URL)\n keySet = new KeySet(\n `${process.env.AUTH_SERVICE_URL}/.well-known/jwks.json`,\n { internal: true }\n );\n else\n keySet = new KeySet(`./keys/jwks.json`, { internal: true, file: true });\n\n if (!keySet)\n throw new EngineError({\n message:\n 'Environment variable \"AUTH_SERVICE_URL\" is not defined or JWKS not found'\n });\n }\n const promise = [keySet.init.bind(keySet)()];\n\n await Promise.all(promise);\n}\n\n/** Stop fetching keys regularly */\nexport function shutdownKeySets(): void {\n if (keySet) keySet.shutdown.bind(keySet)();\n}\n\n/** Get the JWT public key */\nfunction jwtGetKey(header: JwtHeader, callback: SigningKeyCallback): void {\n // In test environment we return the symmetric signature secret\n if (process.env.NODE_ENV === 'test') {\n callback(null, process.env.JWT_SECRET);\n return;\n }\n // Check that KeySet has been initialized\n if (!keySet) {\n callback(new EngineError({ message: 'KeySet has not been initialized' }));\n return;\n }\n // Check that the token has a key ID\n if (!header.kid) {\n callback(\n new EngineError({\n message:\n 'Token has not key ID in header, impossible to match with known key',\n data: header\n })\n );\n return;\n }\n\n // In test environment we use a symmetrical secret bases signature\n if (process.env.NODE_ENV === 'test') {\n callback(null, process.env.JWT_SECRET);\n return;\n }\n reportDebug({\n namespace,\n message: `Looking for key with ID \"${header.kid}\"`\n });\n // Go through each key set to check if the token's key is in one of them\n let key;\n try {\n key = keySet.getKey(header.kid);\n } catch (error: Error | null | unknown) {\n callback(error instanceof Error ? error : null);\n return;\n }\n\n if (key) {\n reportDebug({ namespace, message: `Found key with ID \"${header.kid}\"` });\n callback(null, key);\n return;\n }\n callback(\n new WebError({\n statusCode: 401,\n errorCode: 'unauthorized',\n message: 'Could not find the tokens key in any key set',\n data: { kid: header.kid }\n })\n );\n}\n\n/** Verify an user Json Web Token */\nexport async function jwtVerify(\n token: string,\n issuer: TokenIssuer = TokenIssuer.AUTH_SERVICE\n): Promise<UserTokenPayload> {\n let algorithms = ['ES256' as Algorithm];\n if (process.env.NODE_ENV === 'test') {\n assertEnvironment({ JWT_SECRET: envAssert.isString() });\n algorithms = ['HS256' as Algorithm];\n }\n assertEnvironment({\n ACCESS_TOKEN_AUDIENCE: envAssert.isString(),\n ACCESS_TOKEN_ISSUER: envAssert.isString()\n });\n let options: VerifyOptions | undefined;\n\n switch (issuer) {\n case TokenIssuer.AUTH_SERVICE:\n options = {\n audience: [process.env.ACCESS_TOKEN_AUDIENCE as string],\n issuer: [process.env.ACCESS_TOKEN_ISSUER as string],\n algorithms\n };\n break;\n default:\n throw new EngineError({\n message: `Invalid token issuer specified \"${issuer as string}\"`\n });\n }\n\n return new Promise<UserTokenPayload>((resolve, reject) => {\n verify(token, jwtGetKey, options, (error, result) => {\n if (error) {\n reject(\n new WebError({\n errorCode: 'unauthorized',\n statusCode: 401,\n message: 'Invalid token supplied',\n data: { token },\n error: error instanceof Error ? error : undefined\n })\n );\n return;\n }\n resolve(result as UserTokenPayload);\n });\n });\n}\n\nexport function generateJwtToken(user: unknown) {\n const signOptions = {\n algorithm: 'ES256' as const, // or 'ES256' as Algorithm\n expiresIn: '1h',\n issuer: process.env.ACCESS_TOKEN_ISSUER,\n audience: process.env.ACCESS_TOKEN_AUDIENCE,\n keyid: Object.keys(keySet?.getKeys() ?? {})[0]\n };\n\n const privateKey = fs.readFileSync(\n process.env.PRIVATE_KEY_PATH ?? 'keys/private-key.pem',\n 'utf8'\n );\n const token = sign({ user }, privateKey, signOptions);\n\n return token;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -15,7 +15,6 @@ var _WebError = require("../../entities/WebError");
|
|
|
15
15
|
require("../../middleware/authHmac/authHmac.types");
|
|
16
16
|
require("../../middleware/authJwt/authJwt.types");
|
|
17
17
|
require("../../middleware/authTls/authTls.types");
|
|
18
|
-
require("../../middleware/authAdmin/authAdmin.types");
|
|
19
18
|
/** Default generic logger */
|
|
20
19
|
function reportInfo(data) {
|
|
21
20
|
return (0, _output.output)({
|
|
@@ -57,7 +56,7 @@ function reportError(error, request) {
|
|
|
57
56
|
logEntry = {
|
|
58
57
|
...logEntry,
|
|
59
58
|
context: {
|
|
60
|
-
user: request.user?.id ?? request.hosts?.join(',')
|
|
59
|
+
user: request.user?.id ?? request.hosts?.join(','),
|
|
61
60
|
httpRequest: {
|
|
62
61
|
url: request.originalUrl,
|
|
63
62
|
method: request.method,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","names":["_output","require","_const","_EngineError","_WebError","reportInfo","data","output","severity","LogSeverity","INFO","message","reportError","error","request","logEntry","Error","stack_trace","stack","ERROR","CRITICAL","EngineError","errorType","constructor","name","WebError","statusCode","undefined","errorCode","context","user","id","hosts","join","
|
|
1
|
+
{"version":3,"file":"report.js","names":["_output","require","_const","_EngineError","_WebError","reportInfo","data","output","severity","LogSeverity","INFO","message","reportError","error","request","logEntry","Error","stack_trace","stack","ERROR","CRITICAL","EngineError","errorType","constructor","name","WebError","statusCode","undefined","errorCode","context","user","id","hosts","join","httpRequest","url","originalUrl","method","referrer","header","userAgent","remoteIp","ip","responseStatusCode","NAMESPACE_SELECTORS","exports","initNamespaceSelector","process","env","DEBUG","split","map","namespace","RegExp","replace","resetNamespaceSelector","debugNamespace","reportDebug","isEngineReport","startsWith","match","some","selector","test","spaces","prefix","length","setNameSpace","globalNamespace","clearNamespace"],"sources":["../../../src/utils/report/report.ts"],"sourcesContent":["import { Request } from 'express';\nimport { output } from './output';\nimport { LogEntry, FullLogEntry } from './output.types';\nimport { DebugLogEntry, InfoLogEntry } from './report.types';\nimport { LogSeverity } from 'const';\nimport { EngineError } from 'entities/EngineError';\nimport { WebError } from 'entities/WebError';\nimport {} from 'middleware/authHmac/authHmac.types';\nimport {} from 'middleware/authJwt/authJwt.types';\nimport {} from 'middleware/authTls/authTls.types';\n\n/** Default generic logger */\nexport function reportInfo(data: InfoLogEntry | string): FullLogEntry {\n return output({\n severity: LogSeverity.INFO,\n ...(typeof data === 'string' ? { message: data } : data)\n });\n}\n\n/** Error specific logger */\nexport function reportError(\n error: unknown | Error | EngineError | WebError,\n request?: Request\n): FullLogEntry {\n let logEntry: LogEntry =\n error instanceof Error\n ? {\n message: error.message,\n stack_trace: error.stack,\n severity: LogSeverity.ERROR\n }\n : {\n message: 'An unknown error occurred',\n data: error,\n severity: LogSeverity.CRITICAL\n };\n\n if (error instanceof EngineError) {\n logEntry = {\n ...logEntry,\n severity: error.severity,\n errorType: error.constructor.name,\n data: error.data,\n '@type':\n !(error instanceof WebError) || error.statusCode >= 500\n ? 'type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent'\n : undefined\n };\n }\n\n if (error instanceof WebError) {\n logEntry = {\n ...logEntry,\n errorCode: error.errorCode,\n statusCode: error.statusCode\n };\n }\n\n if (request) {\n logEntry = {\n ...logEntry,\n context: {\n user:\n request.user?.id ?? request.hosts?.join(','),\n httpRequest: {\n url: request.originalUrl,\n method: request.method,\n referrer: request.header('Referer'),\n userAgent: request.header('User-Agent'),\n remoteIp: request.ip,\n responseStatusCode:\n error instanceof WebError ? error.statusCode : undefined\n }\n }\n };\n }\n\n return output(logEntry);\n}\n\nexport let NAMESPACE_SELECTORS: undefined | Array<RegExp>;\n\n/** Generate the namespace selectors based on the debug variable */\nfunction initNamespaceSelector(): void {\n if (process.env.DEBUG)\n NAMESPACE_SELECTORS = process.env.DEBUG.split(',').map(\n (namespace) => new RegExp('^' + namespace.replace(/\\*/g, '.*?') + '$')\n );\n}\n\n/** Reset the namespace selectors */\nexport function resetNamespaceSelector(): void {\n NAMESPACE_SELECTORS = undefined;\n}\n\nlet debugNamespace: string | undefined;\n\n/** Log a message for debugging purpose, based on a namespace specified in an environment variable */\nexport function reportDebug(data: DebugLogEntry): FullLogEntry | undefined {\n if (!NAMESPACE_SELECTORS) initNamespaceSelector();\n let { namespace } = data;\n const isEngineReport = namespace ? namespace.startsWith('engine') : false;\n\n if (debugNamespace && !isEngineReport) {\n namespace = debugNamespace + ':' + namespace;\n }\n\n const match =\n namespace &&\n NAMESPACE_SELECTORS &&\n NAMESPACE_SELECTORS.some((selector) => selector.test(namespace));\n if (!match) return;\n\n // Generate a prefix with the right most part of the namespace\n const spaces = namespace.split(':');\n const prefix = spaces[spaces.length - 1];\n\n return output({\n severity: LogSeverity.DEBUG,\n ...data,\n message: `[${prefix}] ${data.message}`\n });\n}\n\n/** Specify a global debugging namespace */\nreportDebug.setNameSpace = function (globalNamespace: string): void {\n debugNamespace = globalNamespace;\n};\n\n/** Remove any defined global namespace */\nreportDebug.clearNamespace = function (): void {\n debugNamespace = undefined;\n};\n"],"mappings":";;;;;;;;;;AACA,IAAAA,OAAA,GAAAC,OAAA;AAGA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,YAAA,GAAAF,OAAA;AACA,IAAAG,SAAA,GAAAH,OAAA;AACAA,OAAA;AACAA,OAAA;AACAA,OAAA;AAEA;AACO,SAASI,UAAUA,CAACC,IAA2B,EAAgB;EACpE,OAAO,IAAAC,cAAM,EAAC;IACZC,QAAQ,EAAEC,kBAAW,CAACC,IAAI;IAC1B,IAAI,OAAOJ,IAAI,KAAK,QAAQ,GAAG;MAAEK,OAAO,EAAEL;IAAK,CAAC,GAAGA,IAAI;EACzD,CAAC,CAAC;AACJ;;AAEA;AACO,SAASM,WAAWA,CACzBC,KAA+C,EAC/CC,OAAiB,EACH;EACd,IAAIC,QAAkB,GACpBF,KAAK,YAAYG,KAAK,GAClB;IACEL,OAAO,EAAEE,KAAK,CAACF,OAAO;IACtBM,WAAW,EAAEJ,KAAK,CAACK,KAAK;IACxBV,QAAQ,EAAEC,kBAAW,CAACU;EACxB,CAAC,GACD;IACER,OAAO,EAAE,2BAA2B;IACpCL,IAAI,EAAEO,KAAK;IACXL,QAAQ,EAAEC,kBAAW,CAACW;EACxB,CAAC;EAEP,IAAIP,KAAK,YAAYQ,wBAAW,EAAE;IAChCN,QAAQ,GAAG;MACT,GAAGA,QAAQ;MACXP,QAAQ,EAAEK,KAAK,CAACL,QAAQ;MACxBc,SAAS,EAAET,KAAK,CAACU,WAAW,CAACC,IAAI;MACjClB,IAAI,EAAEO,KAAK,CAACP,IAAI;MAChB,OAAO,EACL,EAAEO,KAAK,YAAYY,kBAAQ,CAAC,IAAIZ,KAAK,CAACa,UAAU,IAAI,GAAG,GACnD,oFAAoF,GACpFC;IACR,CAAC;EACH;EAEA,IAAId,KAAK,YAAYY,kBAAQ,EAAE;IAC7BV,QAAQ,GAAG;MACT,GAAGA,QAAQ;MACXa,SAAS,EAAEf,KAAK,CAACe,SAAS;MAC1BF,UAAU,EAAEb,KAAK,CAACa;IACpB,CAAC;EACH;EAEA,IAAIZ,OAAO,EAAE;IACXC,QAAQ,GAAG;MACT,GAAGA,QAAQ;MACXc,OAAO,EAAE;QACPC,IAAI,EACFhB,OAAO,CAACgB,IAAI,EAAEC,EAAE,IAAIjB,OAAO,CAACkB,KAAK,EAAEC,IAAI,CAAC,GAAG,CAAC;QAC9CC,WAAW,EAAE;UACXC,GAAG,EAAErB,OAAO,CAACsB,WAAW;UACxBC,MAAM,EAAEvB,OAAO,CAACuB,MAAM;UACtBC,QAAQ,EAAExB,OAAO,CAACyB,MAAM,CAAC,SAAS,CAAC;UACnCC,SAAS,EAAE1B,OAAO,CAACyB,MAAM,CAAC,YAAY,CAAC;UACvCE,QAAQ,EAAE3B,OAAO,CAAC4B,EAAE;UACpBC,kBAAkB,EAChB9B,KAAK,YAAYY,kBAAQ,GAAGZ,KAAK,CAACa,UAAU,GAAGC;QACnD;MACF;IACF,CAAC;EACH;EAEA,OAAO,IAAApB,cAAM,EAACQ,QAAQ,CAAC;AACzB;AAEO,IAAI6B,mBAA8C,GAAAC,OAAA,CAAAD,mBAAA;;AAEzD;AACA,SAASE,qBAAqBA,CAAA,EAAS;EACrC,IAAIC,OAAO,CAACC,GAAG,CAACC,KAAK,EACnBJ,OAAA,CAAAD,mBAAA,GAAAA,mBAAmB,GAAGG,OAAO,CAACC,GAAG,CAACC,KAAK,CAACC,KAAK,CAAC,GAAG,CAAC,CAACC,GAAG,CACnDC,SAAS,IAAK,IAAIC,MAAM,CAAC,GAAG,GAAGD,SAAS,CAACE,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,GAAG,CACvE,CAAC;AACL;;AAEA;AACO,SAASC,sBAAsBA,CAAA,EAAS;EAC7CV,OAAA,CAAAD,mBAAA,GAAAA,mBAAmB,GAAGjB,SAAS;AACjC;AAEA,IAAI6B,cAAkC;;AAEtC;AACO,SAASC,WAAWA,CAACnD,IAAmB,EAA4B;EACzE,IAAI,CAACsC,mBAAmB,EAAEE,qBAAqB,CAAC,CAAC;EACjD,IAAI;IAAEM;EAAU,CAAC,GAAG9C,IAAI;EACxB,MAAMoD,cAAc,GAAGN,SAAS,GAAGA,SAAS,CAACO,UAAU,CAAC,QAAQ,CAAC,GAAG,KAAK;EAEzE,IAAIH,cAAc,IAAI,CAACE,cAAc,EAAE;IACrCN,SAAS,GAAGI,cAAc,GAAG,GAAG,GAAGJ,SAAS;EAC9C;EAEA,MAAMQ,KAAK,GACTR,SAAS,IACTR,mBAAmB,IACnBA,mBAAmB,CAACiB,IAAI,CAAEC,QAAQ,IAAKA,QAAQ,CAACC,IAAI,CAACX,SAAS,CAAC,CAAC;EAClE,IAAI,CAACQ,KAAK,EAAE;;EAEZ;EACA,MAAMI,MAAM,GAAGZ,SAAS,CAACF,KAAK,CAAC,GAAG,CAAC;EACnC,MAAMe,MAAM,GAAGD,MAAM,CAACA,MAAM,CAACE,MAAM,GAAG,CAAC,CAAC;EAExC,OAAO,IAAA3D,cAAM,EAAC;IACZC,QAAQ,EAAEC,kBAAW,CAACwC,KAAK;IAC3B,GAAG3C,IAAI;IACPK,OAAO,EAAE,IAAIsD,MAAM,KAAK3D,IAAI,CAACK,OAAO;EACtC,CAAC,CAAC;AACJ;;AAEA;AACA8C,WAAW,CAACU,YAAY,GAAG,UAAUC,eAAuB,EAAQ;EAClEZ,cAAc,GAAGY,eAAe;AAClC,CAAC;;AAED;AACAX,WAAW,CAACY,cAAc,GAAG,YAAkB;EAC7Cb,cAAc,GAAG7B,SAAS;AAC5B,CAAC","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-server-engine",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "Framework used to develop backend services. This package ships with a lot of features to standardize the creation of services, letting you focus on the business logic.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
"lint": "eslint ./src",
|
|
10
10
|
"lint:fix": "eslint ./src --fix",
|
|
11
11
|
"prepublish": "npm run build",
|
|
12
|
+
"prepublishOnly": "npm run build",
|
|
12
13
|
"test": "cross-env NODE_ENV=test nyc --reporter=none mocha test/hooks.ts \"src/**/*.test.ts\"",
|
|
13
|
-
"
|
|
14
|
+
"test:file": "cross-env NODE_ENV=test nyc --reporter=none mocha test/hooks.ts",
|
|
15
|
+
"coverage": "nyc report --report-dir=./.test-coverage --reporter=html --reporter=text",
|
|
14
16
|
"coverage:ci": "nyc report --reporter=text-summary",
|
|
15
|
-
"prepublishOnly": "npm run build",
|
|
16
17
|
"test:ci": "npm run test -- --reporter spec",
|
|
17
18
|
"test:compose": "docker-compose up --abort-on-container-exit --build"
|
|
18
19
|
},
|
|
@@ -44,7 +45,7 @@
|
|
|
44
45
|
"@google/generative-ai": "^0.21.0",
|
|
45
46
|
"ajv": "^8.17.1",
|
|
46
47
|
"axios": "^1.7.9",
|
|
47
|
-
"backend-test-tools": "^1.0.
|
|
48
|
+
"backend-test-tools": "^1.0.6",
|
|
48
49
|
"body-parser": "^1.20.3",
|
|
49
50
|
"busboy": "^1.6.0",
|
|
50
51
|
"callsite": "^1.0.0",
|
|
@@ -104,6 +105,7 @@
|
|
|
104
105
|
"@types/callsite": "^1.0.34",
|
|
105
106
|
"@types/chai": "^5.0.1",
|
|
106
107
|
"@types/chai-as-promised": "^8.0.1",
|
|
108
|
+
"@types/cors": "^2.8.17",
|
|
107
109
|
"@types/express": "^5.0.0",
|
|
108
110
|
"@types/filesize-parser": "^1.5.3",
|
|
109
111
|
"@types/flat": "^5.0.5",
|
|
@@ -130,8 +132,8 @@
|
|
|
130
132
|
"@typescript-eslint/eslint-plugin": "^8.18.1",
|
|
131
133
|
"babel-plugin-istanbul": "^7.0.0",
|
|
132
134
|
"babel-plugin-module-resolver": "^5.0.2",
|
|
133
|
-
"chai": "^5.
|
|
134
|
-
"chai-as-promised": "^
|
|
135
|
+
"chai": "^4.5.0",
|
|
136
|
+
"chai-as-promised": "^7.1.2",
|
|
135
137
|
"cross-env": "^7.0.3",
|
|
136
138
|
"eslint": "^9.17.0",
|
|
137
139
|
"factory-waifu": "^1.0.1",
|
|
@@ -147,7 +149,7 @@
|
|
|
147
149
|
"rimraf": "^6.0.1",
|
|
148
150
|
"shx": "^0.3.4",
|
|
149
151
|
"sinon": "^19.0.2",
|
|
150
|
-
"sinon-chai": "^
|
|
152
|
+
"sinon-chai": "^3.5.0",
|
|
151
153
|
"supertest": "^7.0.0",
|
|
152
154
|
"tmp": "^0.2.3",
|
|
153
155
|
"ts-node": "^10.9.2",
|
package/src/const/tokenIssuer.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
/** Enum to identify access tokens JWT issuers */
|
|
2
2
|
export enum TokenIssuer {
|
|
3
3
|
/** For tokens issued by the auth service */
|
|
4
|
-
AUTH_SERVICE
|
|
5
|
-
/** For tokens issued by the admin API */
|
|
6
|
-
ADMIN_API
|
|
4
|
+
AUTH_SERVICE
|
|
7
5
|
}
|
|
8
6
|
|
|
9
7
|
export const TOKEN_ISSUERS = Object.values(TokenIssuer);
|
|
@@ -176,95 +176,6 @@ describe('Entity - Endpoint', () => {
|
|
|
176
176
|
await server.shutdown();
|
|
177
177
|
});
|
|
178
178
|
|
|
179
|
-
// AUTH ADMIN
|
|
180
|
-
|
|
181
|
-
it('it should authenticate with authAdmin middleware', async () => {
|
|
182
|
-
const email = faker.internet.email();
|
|
183
|
-
const permission = faker.lorem.word();
|
|
184
|
-
const token = generateAccessToken(
|
|
185
|
-
email,
|
|
186
|
-
{
|
|
187
|
-
audience: [process.env.ADMIN_API_ACCESS_TOKEN_AUDIENCE as string],
|
|
188
|
-
issuer: process.env.ADMIN_ACCESS_TOKEN_ISSUER as string
|
|
189
|
-
},
|
|
190
|
-
{ per: permission }
|
|
191
|
-
);
|
|
192
|
-
const endpoint = new Endpoint({
|
|
193
|
-
...config,
|
|
194
|
-
authType: EndpointAuthType.ADMIN,
|
|
195
|
-
authParams: { permission },
|
|
196
|
-
handler: (req: Request, res: Response) => {
|
|
197
|
-
res.sendStatus(200);
|
|
198
|
-
}
|
|
199
|
-
} as EndpointOptions<EndpointAuthType.ADMIN>);
|
|
200
|
-
|
|
201
|
-
endpoint.register(app);
|
|
202
|
-
await request(app)
|
|
203
|
-
.get(PATH)
|
|
204
|
-
.set('Authorization', 'Bearer ' + token)
|
|
205
|
-
.expect(200);
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('it should authenticate with authAdmin middleware and check permission', async () => {
|
|
209
|
-
const email = faker.internet.email();
|
|
210
|
-
const permission = faker.lorem.word();
|
|
211
|
-
const token = generateAccessToken(
|
|
212
|
-
email,
|
|
213
|
-
{
|
|
214
|
-
audience: [process.env.ADMIN_API_ACCESS_TOKEN_AUDIENCE as string],
|
|
215
|
-
issuer: process.env.ADMIN_ACCESS_TOKEN_ISSUER as string
|
|
216
|
-
},
|
|
217
|
-
{ per: permission }
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
const endpoint = new Endpoint({
|
|
221
|
-
...config,
|
|
222
|
-
authType: EndpointAuthType.ADMIN,
|
|
223
|
-
authParams: { permission },
|
|
224
|
-
handler: (req: Request, res: Response) => {
|
|
225
|
-
res.sendStatus(200);
|
|
226
|
-
}
|
|
227
|
-
} as EndpointOptions<EndpointAuthType.ADMIN>);
|
|
228
|
-
|
|
229
|
-
endpoint.register(app);
|
|
230
|
-
await request(app)
|
|
231
|
-
.get(PATH)
|
|
232
|
-
.set('Authorization', 'Bearer ' + token)
|
|
233
|
-
.expect(200);
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it('it should authenticate with authAdmin middleware and check permissions', async () => {
|
|
237
|
-
const email = faker.internet.email();
|
|
238
|
-
const permissions = [
|
|
239
|
-
faker.lorem.word(),
|
|
240
|
-
faker.lorem.word(),
|
|
241
|
-
faker.lorem.word()
|
|
242
|
-
];
|
|
243
|
-
const token = generateAccessToken(
|
|
244
|
-
email,
|
|
245
|
-
{
|
|
246
|
-
audience: [process.env.ADMIN_API_ACCESS_TOKEN_AUDIENCE as string],
|
|
247
|
-
issuer: process.env.ADMIN_ACCESS_TOKEN_ISSUER as string
|
|
248
|
-
},
|
|
249
|
-
{ per: permissions }
|
|
250
|
-
);
|
|
251
|
-
|
|
252
|
-
const endpoint = new Endpoint({
|
|
253
|
-
...config,
|
|
254
|
-
authType: EndpointAuthType.ADMIN,
|
|
255
|
-
authParams: { permission: permissions[1] },
|
|
256
|
-
handler: (req: Request, res: Response) => {
|
|
257
|
-
res.sendStatus(200);
|
|
258
|
-
}
|
|
259
|
-
} as EndpointOptions<EndpointAuthType.ADMIN>);
|
|
260
|
-
|
|
261
|
-
endpoint.register(app);
|
|
262
|
-
await request(app)
|
|
263
|
-
.get(PATH)
|
|
264
|
-
.set('Authorization', 'Bearer ' + token)
|
|
265
|
-
.expect(200);
|
|
266
|
-
});
|
|
267
|
-
|
|
268
179
|
it('it should reject if the user has no valid JWT', async () => {
|
|
269
180
|
const endpoint = new Endpoint({
|
|
270
181
|
...config,
|
|
@@ -15,9 +15,7 @@ import {
|
|
|
15
15
|
authHmac,
|
|
16
16
|
authTls,
|
|
17
17
|
authStatic,
|
|
18
|
-
|
|
19
|
-
FileUploaderConfig,
|
|
20
|
-
RequestAdminProps
|
|
18
|
+
FileUploaderConfig
|
|
21
19
|
} from 'middleware';
|
|
22
20
|
|
|
23
21
|
export enum EndpointMethod {
|
|
@@ -37,8 +35,7 @@ export enum EndpointAuthType {
|
|
|
37
35
|
JWT = 'jwt',
|
|
38
36
|
TLS = 'tls',
|
|
39
37
|
HMAC = 'hmac',
|
|
40
|
-
STATIC = 'static'
|
|
41
|
-
ADMIN = 'admin'
|
|
38
|
+
STATIC = 'static'
|
|
42
39
|
}
|
|
43
40
|
|
|
44
41
|
export const EndpointAuthTypes = Object.values(EndpointAuthType);
|
|
@@ -54,12 +51,6 @@ export type MiddlewareChainElement<T extends EndpointAuthType> =
|
|
|
54
51
|
| Middleware<T>
|
|
55
52
|
| any;
|
|
56
53
|
|
|
57
|
-
/** Auth related parameters used with Admin authentication */
|
|
58
|
-
interface EndpointAuthAdminParams {
|
|
59
|
-
/** [Admin] User permission required to use this endpoint */
|
|
60
|
-
permission: string;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
54
|
/** Auth related parameters used with HMAC authentication */
|
|
64
55
|
interface EndpointAuthHmacParams {
|
|
65
56
|
/** [HMAC] Secret used for signature */
|
|
@@ -86,8 +77,6 @@ interface EndpointAuthSpecificParams {
|
|
|
86
77
|
[EndpointAuthType.HMAC]: EndpointAuthHmacParams;
|
|
87
78
|
/** Auth parameters for static authentication */
|
|
88
79
|
[EndpointAuthType.STATIC]: any;
|
|
89
|
-
/** Auth parameters for admin token authentication */
|
|
90
|
-
[EndpointAuthType.ADMIN]: EndpointAuthAdminParams;
|
|
91
80
|
}
|
|
92
81
|
|
|
93
82
|
export type EndpointAuthParams<T extends EndpointAuthType> =
|
|
@@ -114,9 +103,7 @@ export const EndpointAuthHandlers = {
|
|
|
114
103
|
/** Auth handler for HMAC authentication */
|
|
115
104
|
[EndpointAuthType.HMAC]: authHmac,
|
|
116
105
|
/** Auth handler for static authentication */
|
|
117
|
-
[EndpointAuthType.STATIC]: authStatic
|
|
118
|
-
/** Auth handler for admin token authentication */
|
|
119
|
-
[EndpointAuthType.ADMIN]: authAdmin
|
|
106
|
+
[EndpointAuthType.STATIC]: authStatic
|
|
120
107
|
};
|
|
121
108
|
|
|
122
109
|
export type EndpointHandler<T extends EndpointAuthType> = (
|
|
@@ -172,18 +159,6 @@ export interface TlsRequest<
|
|
|
172
159
|
hosts: Array<string>;
|
|
173
160
|
}
|
|
174
161
|
|
|
175
|
-
/** Request type when using HMAC authentication */
|
|
176
|
-
export interface AdminRequest<
|
|
177
|
-
P = ParamsDictionary,
|
|
178
|
-
ResBody = any,
|
|
179
|
-
ReqBody = any,
|
|
180
|
-
ReqQuery = ParsedQs,
|
|
181
|
-
Locals extends Record<string, any> = Record<string, any>
|
|
182
|
-
> extends Request<P, ResBody, ReqBody, ReqQuery, Locals> {
|
|
183
|
-
/** User that identified using a JWT */
|
|
184
|
-
admin: RequestAdminProps;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
162
|
/** Mapping of request types in endpoints based on auth type used */
|
|
188
163
|
export interface EndpointRequestType {
|
|
189
164
|
/** Request type for no authentication */
|
|
@@ -196,8 +171,6 @@ export interface EndpointRequestType {
|
|
|
196
171
|
[EndpointAuthType.HMAC]: Request;
|
|
197
172
|
/** Auth handler for static authentication */
|
|
198
173
|
[EndpointAuthType.STATIC]: Request;
|
|
199
|
-
/** Auth handler for admin token authentication */
|
|
200
|
-
[EndpointAuthType.ADMIN]: AdminRequest;
|
|
201
174
|
}
|
|
202
175
|
|
|
203
176
|
export type SafeMiddleWareChain = Array<
|
|
@@ -100,7 +100,7 @@ describe('Entity - KeySet', function () {
|
|
|
100
100
|
|
|
101
101
|
it('should read a key from a PEM string', async () => {
|
|
102
102
|
const pem = await readFile(
|
|
103
|
-
process.env.
|
|
103
|
+
process.env.ECDSA_PUBLIC_KEY as string,
|
|
104
104
|
'utf-8'
|
|
105
105
|
);
|
|
106
106
|
|
|
@@ -6,6 +6,7 @@ import path from 'path';
|
|
|
6
6
|
import { setTimeout as setTimeoutPromise } from 'timers/promises';
|
|
7
7
|
import { ValidatorSpec } from 'envalid';
|
|
8
8
|
import express, { Application } from 'express';
|
|
9
|
+
import cors from 'cors';
|
|
9
10
|
import { Server as WebSocketServer } from 'ws';
|
|
10
11
|
import { SocketClient } from '../SocketClient';
|
|
11
12
|
import {
|
|
@@ -110,6 +111,14 @@ export class Server {
|
|
|
110
111
|
|
|
111
112
|
// Create the primary express core that serves the business logic
|
|
112
113
|
this.app = express();
|
|
114
|
+
|
|
115
|
+
this.app.use(
|
|
116
|
+
cors({
|
|
117
|
+
origin: process.env.CORS_ORIGIN ?? '*',
|
|
118
|
+
methods: 'GET,POST,PUT,DELETE'
|
|
119
|
+
})
|
|
120
|
+
);
|
|
121
|
+
|
|
113
122
|
this.registerMiddleware(this.app);
|
|
114
123
|
this.httpServer = createHttpServer(this.app);
|
|
115
124
|
|
package/src/middleware/index.ts
CHANGED
package/src/utils/index.ts
CHANGED
|
@@ -25,17 +25,4 @@ describe('Utils - JWT', () => {
|
|
|
25
25
|
const result = await jwtVerify(token, TokenIssuer.AUTH_SERVICE);
|
|
26
26
|
expect(result.sub).to.equal(id);
|
|
27
27
|
});
|
|
28
|
-
|
|
29
|
-
it('should pass a token with one correct audience [Admin-API]', async () => {
|
|
30
|
-
const id = randomUUID();
|
|
31
|
-
const token = generateAccessToken(id, {
|
|
32
|
-
audience: [
|
|
33
|
-
process.env.ADMIN_API_ACCESS_TOKEN_AUDIENCE as string,
|
|
34
|
-
faker.lorem.word()
|
|
35
|
-
],
|
|
36
|
-
issuer: process.env.ADMIN_ACCESS_TOKEN_ISSUER
|
|
37
|
-
});
|
|
38
|
-
const result = await jwtVerify(token, TokenIssuer.ADMIN_API);
|
|
39
|
-
expect(result.sub).to.equal(id);
|
|
40
|
-
});
|
|
41
28
|
});
|
package/src/utils/jwt/jwt.ts
CHANGED
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
sign
|
|
8
8
|
} from 'jsonwebtoken';
|
|
9
9
|
import fs from 'fs';
|
|
10
|
-
import path from 'path';
|
|
11
10
|
import { UserTokenPayload } from './jwt.types';
|
|
12
11
|
import { TokenIssuer } from 'const';
|
|
13
12
|
import { EngineError } from 'entities/EngineError';
|
|
@@ -18,7 +17,6 @@ import { envAssert } from 'utils/envAssert';
|
|
|
18
17
|
import { reportDebug } from 'utils/report';
|
|
19
18
|
|
|
20
19
|
export let keySet: KeySet | undefined;
|
|
21
|
-
export let adminKeySet: KeySet | undefined;
|
|
22
20
|
|
|
23
21
|
const namespace = 'engine:utils:jwt';
|
|
24
22
|
|
|
@@ -50,24 +48,12 @@ export async function initKeySets(): Promise<void> {
|
|
|
50
48
|
}
|
|
51
49
|
const promise = [keySet.init.bind(keySet)()];
|
|
52
50
|
|
|
53
|
-
// Load the key set for the admin api
|
|
54
|
-
if (!process.env.ADMIN_API_ECDSA_PUBLIC_KEY)
|
|
55
|
-
throw new EngineError({
|
|
56
|
-
message:
|
|
57
|
-
"Admin API's authentication JWT signing public key is not defined"
|
|
58
|
-
});
|
|
59
|
-
adminKeySet = new KeySet(process.env.ADMIN_API_ECDSA_PUBLIC_KEY, {
|
|
60
|
-
pem: true
|
|
61
|
-
});
|
|
62
|
-
promise.push(adminKeySet.init.bind(adminKeySet)());
|
|
63
|
-
|
|
64
51
|
await Promise.all(promise);
|
|
65
52
|
}
|
|
66
53
|
|
|
67
54
|
/** Stop fetching keys regularly */
|
|
68
55
|
export function shutdownKeySets(): void {
|
|
69
56
|
if (keySet) keySet.shutdown.bind(keySet)();
|
|
70
|
-
if (adminKeySet) adminKeySet.shutdown.bind(adminKeySet)();
|
|
71
57
|
}
|
|
72
58
|
|
|
73
59
|
/** Get the JWT public key */
|
|
@@ -78,7 +64,7 @@ function jwtGetKey(header: JwtHeader, callback: SigningKeyCallback): void {
|
|
|
78
64
|
return;
|
|
79
65
|
}
|
|
80
66
|
// Check that KeySet has been initialized
|
|
81
|
-
if (!keySet
|
|
67
|
+
if (!keySet) {
|
|
82
68
|
callback(new EngineError({ message: 'KeySet has not been initialized' }));
|
|
83
69
|
return;
|
|
84
70
|
}
|
|
@@ -139,9 +125,7 @@ export async function jwtVerify(
|
|
|
139
125
|
}
|
|
140
126
|
assertEnvironment({
|
|
141
127
|
ACCESS_TOKEN_AUDIENCE: envAssert.isString(),
|
|
142
|
-
ACCESS_TOKEN_ISSUER: envAssert.isString()
|
|
143
|
-
ADMIN_API_ACCESS_TOKEN_AUDIENCE: envAssert.isString(),
|
|
144
|
-
ADMIN_ACCESS_TOKEN_ISSUER: envAssert.isString()
|
|
128
|
+
ACCESS_TOKEN_ISSUER: envAssert.isString()
|
|
145
129
|
});
|
|
146
130
|
let options: VerifyOptions | undefined;
|
|
147
131
|
|
|
@@ -153,13 +137,6 @@ export async function jwtVerify(
|
|
|
153
137
|
algorithms
|
|
154
138
|
};
|
|
155
139
|
break;
|
|
156
|
-
case TokenIssuer.ADMIN_API:
|
|
157
|
-
options = {
|
|
158
|
-
audience: [process.env.ADMIN_API_ACCESS_TOKEN_AUDIENCE as string],
|
|
159
|
-
issuer: [process.env.ADMIN_ACCESS_TOKEN_ISSUER as string],
|
|
160
|
-
algorithms
|
|
161
|
-
};
|
|
162
|
-
break;
|
|
163
140
|
default:
|
|
164
141
|
throw new EngineError({
|
|
165
142
|
message: `Invalid token issuer specified "${issuer as string}"`
|
|
@@ -8,7 +8,6 @@ import { WebError } from 'entities/WebError';
|
|
|
8
8
|
import {} from 'middleware/authHmac/authHmac.types';
|
|
9
9
|
import {} from 'middleware/authJwt/authJwt.types';
|
|
10
10
|
import {} from 'middleware/authTls/authTls.types';
|
|
11
|
-
import {} from 'middleware/authAdmin/authAdmin.types';
|
|
12
11
|
|
|
13
12
|
/** Default generic logger */
|
|
14
13
|
export function reportInfo(data: InfoLogEntry | string): FullLogEntry {
|
|
@@ -62,7 +61,7 @@ export function reportError(
|
|
|
62
61
|
...logEntry,
|
|
63
62
|
context: {
|
|
64
63
|
user:
|
|
65
|
-
request.user?.id ?? request.hosts?.join(',')
|
|
64
|
+
request.user?.id ?? request.hosts?.join(','),
|
|
66
65
|
httpRequest: {
|
|
67
66
|
url: request.originalUrl,
|
|
68
67
|
method: request.method,
|
package/test/env.ts
CHANGED
|
@@ -15,10 +15,7 @@ process.env = {
|
|
|
15
15
|
PAYLOAD_SIGNATURE_SECRET: faker.lorem.word(),
|
|
16
16
|
ACCESS_TOKEN_AUDIENCE: audience,
|
|
17
17
|
ACCESS_TOKEN_ISSUER: faker.lorem.word(),
|
|
18
|
-
ADMIN_API_ACCESS_TOKEN_AUDIENCE: audience,
|
|
19
|
-
ADMIN_ACCESS_TOKEN_ISSUER: faker.lorem.word(),
|
|
20
18
|
AUTH_SERVICE_PUBLIC_URL: faker.internet.url(),
|
|
21
|
-
ADMIN_API_PUBLIC_URL: faker.internet.url(),
|
|
22
19
|
VALID_IPS: '::ffff:127.0.0.1,127.0.0.1,::1',
|
|
23
20
|
REDIS_HOST: process.env.REDIS_HOST ?? '127.0.0.1',
|
|
24
21
|
REDIS_PORT: '6379',
|
|
@@ -33,9 +30,7 @@ process.env = {
|
|
|
33
30
|
TLS_REQUEST_KEY_PASSPHRASE: path.resolve('certs/ecdsa.key.pub'),
|
|
34
31
|
ECDSA_PRIVATE_KEY: path.resolve('certs/ecdsa.key'),
|
|
35
32
|
ECDSA_PUBLIC_KEY: path.resolve('certs/ecdsa.key.pub'),
|
|
36
|
-
ADMIN_API_ECDSA_PUBLIC_KEY: path.resolve('certs/ecdsa.key.pub'),
|
|
37
33
|
GITHUB_WEBHOOK_SECRET: faker.lorem.word(),
|
|
38
|
-
LINKS_SERVICE_URL: faker.internet.url(),
|
|
39
34
|
STATIC_TOKEN: faker.lorem.word(),
|
|
40
35
|
HOSTNAME: faker.lorem.slug(),
|
|
41
36
|
ELASTIC_SEARCH_HOST:
|
package/test/hooks.ts
CHANGED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { Request, Response, NextFunction } from 'express';
|
|
2
|
-
import { EndpointAuthParams, EndpointAuthType } from '../../entities/Endpoint';
|
|
3
|
-
/** Generate a middleware to authenticate the client connection with a Admin api */
|
|
4
|
-
export declare function authAdmin(options: EndpointAuthParams<EndpointAuthType.ADMIN>): (request: Request, response: Response, next: NextFunction) => Promise<void>;
|