@flink-app/jwt-auth-plugin 0.11.5 → 0.11.14
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/package.json +3 -3
- package/dist/spec/FlinkJwtAuthPlugin.spec.d.ts +0 -1
- package/dist/spec/FlinkJwtAuthPlugin.spec.js +0 -193
- package/dist/spec/PermissionValidator.spec.d.ts +0 -1
- package/dist/spec/PermissionValidator.spec.js +0 -45
- package/dist/src/BcryptUtils.d.ts +0 -2
- package/dist/src/BcryptUtils.js +0 -27
- package/dist/src/FlinkJwtAuthPlugin.d.ts +0 -41
- package/dist/src/FlinkJwtAuthPlugin.js +0 -180
- package/dist/src/PermissionValidator.d.ts +0 -12
- package/dist/src/PermissionValidator.js +0 -43
- package/dist/src/index.d.ts +0 -1
- package/dist/src/index.js +0 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flink-app/jwt-auth-plugin",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.14",
|
|
4
4
|
"description": "Flink plugin for JWT auth",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --preserve-symlinks -r ts-node/register -- node_modules/jasmine/bin/jasmine --config=./spec/support/jasmine.json",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"jwt-simple": "^0.5.6"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@flink-app/flink": "^0.11.
|
|
23
|
+
"@flink-app/flink": "^0.11.14",
|
|
24
24
|
"@types/bcrypt": "^5.0.0",
|
|
25
25
|
"@types/jasmine": "^3.7.1",
|
|
26
26
|
"@types/node": "^15.6.2",
|
|
@@ -31,5 +31,5 @@
|
|
|
31
31
|
"tsc-watch": "^4.2.9",
|
|
32
32
|
"typescript": "^4.2.4"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "8172291cf7330d13c7958d170100fe9771fd7dfb"
|
|
35
35
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,193 +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
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
-
};
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
var jwt_simple_1 = __importDefault(require("jwt-simple"));
|
|
43
|
-
var FlinkJwtAuthPlugin_1 = require("../src/FlinkJwtAuthPlugin");
|
|
44
|
-
describe("FlinkJwtAuthPlugin", function () {
|
|
45
|
-
it("should create and configure plugin", function () {
|
|
46
|
-
var plugin = (0, FlinkJwtAuthPlugin_1.jwtAuthPlugin)({
|
|
47
|
-
secret: "secret",
|
|
48
|
-
getUser: function (id) { return __awaiter(void 0, void 0, void 0, function () {
|
|
49
|
-
return __generator(this, function (_a) {
|
|
50
|
-
return [2 /*return*/, {
|
|
51
|
-
id: id,
|
|
52
|
-
username: "username",
|
|
53
|
-
}];
|
|
54
|
-
});
|
|
55
|
-
}); },
|
|
56
|
-
rolePermissions: {},
|
|
57
|
-
});
|
|
58
|
-
expect(plugin).toBeDefined();
|
|
59
|
-
});
|
|
60
|
-
it("should fail auth if no token was provided", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
61
|
-
var plugin, mockRequest, authenticated;
|
|
62
|
-
return __generator(this, function (_a) {
|
|
63
|
-
switch (_a.label) {
|
|
64
|
-
case 0:
|
|
65
|
-
plugin = (0, FlinkJwtAuthPlugin_1.jwtAuthPlugin)({
|
|
66
|
-
secret: "secret",
|
|
67
|
-
getUser: function (id) { return __awaiter(void 0, void 0, void 0, function () {
|
|
68
|
-
return __generator(this, function (_a) {
|
|
69
|
-
return [2 /*return*/, {
|
|
70
|
-
id: id,
|
|
71
|
-
username: "username",
|
|
72
|
-
}];
|
|
73
|
-
});
|
|
74
|
-
}); },
|
|
75
|
-
rolePermissions: {
|
|
76
|
-
user: ["*"],
|
|
77
|
-
},
|
|
78
|
-
});
|
|
79
|
-
mockRequest = {
|
|
80
|
-
headers: {
|
|
81
|
-
authorization: "",
|
|
82
|
-
},
|
|
83
|
-
};
|
|
84
|
-
return [4 /*yield*/, plugin.authenticateRequest(mockRequest, "foo")];
|
|
85
|
-
case 1:
|
|
86
|
-
authenticated = _a.sent();
|
|
87
|
-
expect(authenticated).toBeFalse();
|
|
88
|
-
return [2 /*return*/];
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
}); });
|
|
92
|
-
it("should fail auth if token is invalid provided", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
93
|
-
var plugin, mockRequest, authenticated;
|
|
94
|
-
return __generator(this, function (_a) {
|
|
95
|
-
switch (_a.label) {
|
|
96
|
-
case 0:
|
|
97
|
-
plugin = (0, FlinkJwtAuthPlugin_1.jwtAuthPlugin)({
|
|
98
|
-
secret: "secret",
|
|
99
|
-
getUser: function (id) { return __awaiter(void 0, void 0, void 0, function () {
|
|
100
|
-
return __generator(this, function (_a) {
|
|
101
|
-
fail(); // Should not invoke this
|
|
102
|
-
return [2 /*return*/, {
|
|
103
|
-
id: id,
|
|
104
|
-
username: "username",
|
|
105
|
-
}];
|
|
106
|
-
});
|
|
107
|
-
}); },
|
|
108
|
-
rolePermissions: {
|
|
109
|
-
user: ["*"],
|
|
110
|
-
},
|
|
111
|
-
});
|
|
112
|
-
mockRequest = {
|
|
113
|
-
headers: {
|
|
114
|
-
authorization: "Bearer 890suf089sudf0usdf0uf9s",
|
|
115
|
-
},
|
|
116
|
-
};
|
|
117
|
-
return [4 /*yield*/, plugin.authenticateRequest(mockRequest, "foo")];
|
|
118
|
-
case 1:
|
|
119
|
-
authenticated = _a.sent();
|
|
120
|
-
expect(authenticated).toBeFalse();
|
|
121
|
-
return [2 /*return*/];
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
}); });
|
|
125
|
-
it("should decode token and authenticate", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
126
|
-
var secret, userId, encodedToken, plugin, mockRequest, authenticated;
|
|
127
|
-
return __generator(this, function (_a) {
|
|
128
|
-
switch (_a.label) {
|
|
129
|
-
case 0:
|
|
130
|
-
secret = "secret";
|
|
131
|
-
userId = "123";
|
|
132
|
-
encodedToken = jwt_simple_1.default.encode({ id: userId, roles: ["user"] }, secret);
|
|
133
|
-
plugin = (0, FlinkJwtAuthPlugin_1.jwtAuthPlugin)({
|
|
134
|
-
secret: secret,
|
|
135
|
-
getUser: function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
|
|
136
|
-
var id = _b.id;
|
|
137
|
-
return __generator(this, function (_c) {
|
|
138
|
-
expect(id).toBe(userId);
|
|
139
|
-
return [2 /*return*/, {
|
|
140
|
-
id: id,
|
|
141
|
-
username: "username",
|
|
142
|
-
}];
|
|
143
|
-
});
|
|
144
|
-
}); },
|
|
145
|
-
rolePermissions: {
|
|
146
|
-
user: ["*"],
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
mockRequest = {
|
|
150
|
-
headers: {
|
|
151
|
-
authorization: "Bearer " + encodedToken,
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
return [4 /*yield*/, plugin.authenticateRequest(mockRequest, "foo")];
|
|
155
|
-
case 1:
|
|
156
|
-
authenticated = _a.sent();
|
|
157
|
-
expect(authenticated).toBeTruthy();
|
|
158
|
-
return [2 /*return*/];
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
}); });
|
|
162
|
-
it("should generate token", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
163
|
-
var secret, plugin, token, decoded;
|
|
164
|
-
return __generator(this, function (_a) {
|
|
165
|
-
switch (_a.label) {
|
|
166
|
-
case 0:
|
|
167
|
-
secret = "secret";
|
|
168
|
-
plugin = (0, FlinkJwtAuthPlugin_1.jwtAuthPlugin)({
|
|
169
|
-
secret: secret,
|
|
170
|
-
getUser: function (id) { return __awaiter(void 0, void 0, void 0, function () {
|
|
171
|
-
return __generator(this, function (_a) {
|
|
172
|
-
fail(); // Should not invoke this
|
|
173
|
-
return [2 /*return*/, {
|
|
174
|
-
id: id,
|
|
175
|
-
username: "username",
|
|
176
|
-
}];
|
|
177
|
-
});
|
|
178
|
-
}); },
|
|
179
|
-
rolePermissions: {
|
|
180
|
-
user: ["*"],
|
|
181
|
-
},
|
|
182
|
-
});
|
|
183
|
-
return [4 /*yield*/, plugin.createToken({ id: "123" }, ["user"])];
|
|
184
|
-
case 1:
|
|
185
|
-
token = _a.sent();
|
|
186
|
-
expect(token).toBeDefined();
|
|
187
|
-
decoded = jwt_simple_1.default.decode(token, secret);
|
|
188
|
-
expect(decoded.id).toBe("123");
|
|
189
|
-
return [2 /*return*/];
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
}); });
|
|
193
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
var PermissionValidator_1 = require("../src/PermissionValidator");
|
|
4
|
-
describe("PermissionValidator", function () {
|
|
5
|
-
it("should validate permissions if *", function () {
|
|
6
|
-
var valid = (0, PermissionValidator_1.hasValidPermissions)(["user"], {
|
|
7
|
-
user: ["foo", "*"],
|
|
8
|
-
}, ["bar"]);
|
|
9
|
-
expect(valid).toBe(true);
|
|
10
|
-
});
|
|
11
|
-
it("should validate permissions if match", function () {
|
|
12
|
-
var valid = (0, PermissionValidator_1.hasValidPermissions)(["user"], {
|
|
13
|
-
user: ["foo"],
|
|
14
|
-
}, ["foo"]);
|
|
15
|
-
expect(valid).toBe(true);
|
|
16
|
-
});
|
|
17
|
-
it("should not validate permissions if no match", function () {
|
|
18
|
-
var valid = (0, PermissionValidator_1.hasValidPermissions)(["user"], {
|
|
19
|
-
user: ["foo"],
|
|
20
|
-
}, ["bar"]);
|
|
21
|
-
expect(valid).toBe(false);
|
|
22
|
-
});
|
|
23
|
-
it("should not validate permissions if role permissions are missing", function () {
|
|
24
|
-
var valid = (0, PermissionValidator_1.hasValidPermissions)(["user"], {}, ["bar"]);
|
|
25
|
-
expect(valid).toBe(false);
|
|
26
|
-
});
|
|
27
|
-
it("should not validate permissions if only partial permission is matching", function () {
|
|
28
|
-
var valid = (0, PermissionValidator_1.hasValidPermissions)(["user"], {
|
|
29
|
-
user: ["foo"],
|
|
30
|
-
}, ["foo", "bar"]);
|
|
31
|
-
expect(valid).toBe(false);
|
|
32
|
-
});
|
|
33
|
-
it("should validate if public route", function () {
|
|
34
|
-
var valid = (0, PermissionValidator_1.hasValidPermissions)([], {}, []);
|
|
35
|
-
expect(valid).toBe(true);
|
|
36
|
-
});
|
|
37
|
-
it("should validate if any authenticated user is allowed", function () {
|
|
38
|
-
var valid = (0, PermissionValidator_1.hasValidPermissions)(["user"], {}, ["*"]);
|
|
39
|
-
expect(valid).toBe(true);
|
|
40
|
-
});
|
|
41
|
-
it("should not validate if any authenticated user is allowed but user not logged in", function () {
|
|
42
|
-
var valid = (0, PermissionValidator_1.hasValidPermissions)([], {}, ["*"]);
|
|
43
|
-
expect(valid).toBe(false);
|
|
44
|
-
});
|
|
45
|
-
});
|
package/dist/src/BcryptUtils.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.encrypt = encrypt;
|
|
7
|
-
exports.genSalt = genSalt;
|
|
8
|
-
var bcrypt_1 = __importDefault(require("bcrypt"));
|
|
9
|
-
function encrypt(password, salt) {
|
|
10
|
-
return new Promise(function (resolve, reject) {
|
|
11
|
-
bcrypt_1.default.hash(password, salt, function (err, hash) {
|
|
12
|
-
if (err)
|
|
13
|
-
reject(err);
|
|
14
|
-
resolve(hash);
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
function genSalt(rounds) {
|
|
19
|
-
if (rounds === void 0) { rounds = 10; }
|
|
20
|
-
return new Promise(function (resolve, reject) {
|
|
21
|
-
bcrypt_1.default.genSalt(rounds, function (err, salt) {
|
|
22
|
-
if (err)
|
|
23
|
-
reject(err);
|
|
24
|
-
resolve(salt);
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { FlinkAuthPlugin, FlinkAuthUser } from "@flink-app/flink";
|
|
2
|
-
import jwtSimple from "jwt-simple";
|
|
3
|
-
export interface JwtAuthPluginOptions {
|
|
4
|
-
secret: string;
|
|
5
|
-
algo?: jwtSimple.TAlgorithm;
|
|
6
|
-
getUser: (tokenData: any) => Promise<FlinkAuthUser>;
|
|
7
|
-
passwordPolicy?: RegExp;
|
|
8
|
-
tokenTTL?: number;
|
|
9
|
-
rolePermissions: {
|
|
10
|
-
[role: string]: string[];
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
export interface JwtAuthPlugin extends FlinkAuthPlugin {
|
|
14
|
-
/**
|
|
15
|
-
* Encodes and returns JWT token that includes provided payload.
|
|
16
|
-
*
|
|
17
|
-
* The payload can by anything but should in most cases be and object that
|
|
18
|
-
* holds user information including an identifier such as the username or id.
|
|
19
|
-
*/
|
|
20
|
-
createToken: (payload: any, roles: string[]) => Promise<string>;
|
|
21
|
-
/**
|
|
22
|
-
* Generates new password hash and salt for provided password.
|
|
23
|
-
*
|
|
24
|
-
* This method should be used when setting a new password. Both hash and salt needs
|
|
25
|
-
* to be saved in database as both are needed to validate the password.
|
|
26
|
-
*
|
|
27
|
-
* Returns null if password does not match configured `passwordPolicy`.
|
|
28
|
-
*/
|
|
29
|
-
createPasswordHashAndSalt: (password: string) => Promise<{
|
|
30
|
-
hash: string;
|
|
31
|
-
salt: string;
|
|
32
|
-
} | null>;
|
|
33
|
-
/**
|
|
34
|
-
* Validates that provided `password` is same as provided `hash`.
|
|
35
|
-
*/
|
|
36
|
-
validatePassword: (password: string, passwordHash: string, salt: string) => Promise<boolean>;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Configures and creates authentication plugin.
|
|
40
|
-
*/
|
|
41
|
-
export declare function jwtAuthPlugin({ secret, getUser, rolePermissions, algo, passwordPolicy, tokenTTL, }: JwtAuthPluginOptions): JwtAuthPlugin;
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
24
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
-
function step(op) {
|
|
27
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
-
switch (op[0]) {
|
|
32
|
-
case 0: case 1: t = op; break;
|
|
33
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
-
default:
|
|
37
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
-
if (t[2]) _.ops.pop();
|
|
42
|
-
_.trys.pop(); continue;
|
|
43
|
-
}
|
|
44
|
-
op = body.call(thisArg, _);
|
|
45
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
50
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
51
|
-
};
|
|
52
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
-
exports.jwtAuthPlugin = jwtAuthPlugin;
|
|
54
|
-
var flink_1 = require("@flink-app/flink");
|
|
55
|
-
var jwt_simple_1 = __importDefault(require("jwt-simple"));
|
|
56
|
-
var BcryptUtils_1 = require("./BcryptUtils");
|
|
57
|
-
var PermissionValidator_1 = require("./PermissionValidator");
|
|
58
|
-
/**
|
|
59
|
-
* Minimum eight characters, at least one letter and one number
|
|
60
|
-
* https://stackoverflow.com/a/21456918
|
|
61
|
-
*/
|
|
62
|
-
var defaultPasswordPolicy = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/;
|
|
63
|
-
/**
|
|
64
|
-
* Configures and creates authentication plugin.
|
|
65
|
-
*/
|
|
66
|
-
function jwtAuthPlugin(_a) {
|
|
67
|
-
var _this = this;
|
|
68
|
-
var secret = _a.secret, getUser = _a.getUser, rolePermissions = _a.rolePermissions, _b = _a.algo, algo = _b === void 0 ? "HS256" : _b, _c = _a.passwordPolicy, passwordPolicy = _c === void 0 ? defaultPasswordPolicy : _c, _d = _a.tokenTTL, tokenTTL = _d === void 0 ? 1000 * 60 * 60 * 24 * 365 * 100 : _d;
|
|
69
|
-
return {
|
|
70
|
-
authenticateRequest: function (req, permissions) { return __awaiter(_this, void 0, void 0, function () {
|
|
71
|
-
return __generator(this, function (_a) {
|
|
72
|
-
return [2 /*return*/, authenticateRequest(req, permissions, rolePermissions, {
|
|
73
|
-
algo: algo,
|
|
74
|
-
secret: secret,
|
|
75
|
-
getUser: getUser,
|
|
76
|
-
})];
|
|
77
|
-
});
|
|
78
|
-
}); },
|
|
79
|
-
createToken: function (payload, roles) {
|
|
80
|
-
return createToken(__assign(__assign({}, payload), { roles: roles }), { algo: algo, secret: secret, tokenTTL: tokenTTL });
|
|
81
|
-
},
|
|
82
|
-
createPasswordHashAndSalt: function (password) {
|
|
83
|
-
return createPasswordHashAndSalt(password, passwordPolicy);
|
|
84
|
-
},
|
|
85
|
-
validatePassword: validatePassword,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
function authenticateRequest(req_1, routePermissions_1, rolePermissions_1, _a) {
|
|
89
|
-
return __awaiter(this, arguments, void 0, function (req, routePermissions, rolePermissions, _b) {
|
|
90
|
-
var token, decodedToken, permissionsArr, validPerms, user;
|
|
91
|
-
var secret = _b.secret, algo = _b.algo, getUser = _b.getUser;
|
|
92
|
-
return __generator(this, function (_c) {
|
|
93
|
-
switch (_c.label) {
|
|
94
|
-
case 0:
|
|
95
|
-
token = getTokenFromReq(req);
|
|
96
|
-
if (!token) return [3 /*break*/, 2];
|
|
97
|
-
decodedToken = void 0;
|
|
98
|
-
try {
|
|
99
|
-
decodedToken = jwt_simple_1.default.decode(token, secret, false, algo);
|
|
100
|
-
}
|
|
101
|
-
catch (err) {
|
|
102
|
-
flink_1.log.debug("Failed to decode token: ".concat(err));
|
|
103
|
-
decodedToken = null;
|
|
104
|
-
}
|
|
105
|
-
if (!decodedToken) return [3 /*break*/, 2];
|
|
106
|
-
permissionsArr = Array.isArray(routePermissions)
|
|
107
|
-
? routePermissions
|
|
108
|
-
: [routePermissions];
|
|
109
|
-
if (permissionsArr && permissionsArr.length > 0) {
|
|
110
|
-
validPerms = (0, PermissionValidator_1.hasValidPermissions)(decodedToken.roles || [], rolePermissions, permissionsArr);
|
|
111
|
-
if (!validPerms) {
|
|
112
|
-
return [2 /*return*/, false];
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return [4 /*yield*/, getUser(decodedToken)];
|
|
116
|
-
case 1:
|
|
117
|
-
user = _c.sent();
|
|
118
|
-
req.user = user;
|
|
119
|
-
return [2 /*return*/, true];
|
|
120
|
-
case 2: return [2 /*return*/, false];
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
function getTokenFromReq(req) {
|
|
126
|
-
var authHeader = req.headers.authorization;
|
|
127
|
-
if (authHeader) {
|
|
128
|
-
var _a = authHeader.split("Bearer "), token = _a[1];
|
|
129
|
-
return token;
|
|
130
|
-
}
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
function createToken(payload_1, _a) {
|
|
134
|
-
return __awaiter(this, arguments, void 0, function (payload, _b) {
|
|
135
|
-
var secret = _b.secret, algo = _b.algo, tokenTTL = _b.tokenTTL;
|
|
136
|
-
return __generator(this, function (_c) {
|
|
137
|
-
if (!payload) {
|
|
138
|
-
throw new Error("Cannot create token - payload is missing");
|
|
139
|
-
}
|
|
140
|
-
return [2 /*return*/, jwt_simple_1.default.encode(__assign({ exp: _calculateExpiration(tokenTTL || 1000 * 60 * 60 * 24 * 365 * 100) }, payload), secret, algo)];
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
function _calculateExpiration(expiresInMs) {
|
|
145
|
-
return Math.floor((Date.now() + expiresInMs) / 1000);
|
|
146
|
-
}
|
|
147
|
-
function createPasswordHashAndSalt(password, passwordPolicy) {
|
|
148
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
149
|
-
var salt, hash;
|
|
150
|
-
return __generator(this, function (_a) {
|
|
151
|
-
switch (_a.label) {
|
|
152
|
-
case 0:
|
|
153
|
-
if (!passwordPolicy.test(password)) {
|
|
154
|
-
flink_1.log.debug("Password does not match password policy '".concat(passwordPolicy, "'"));
|
|
155
|
-
return [2 /*return*/, null];
|
|
156
|
-
}
|
|
157
|
-
return [4 /*yield*/, (0, BcryptUtils_1.genSalt)(10)];
|
|
158
|
-
case 1:
|
|
159
|
-
salt = _a.sent();
|
|
160
|
-
return [4 /*yield*/, (0, BcryptUtils_1.encrypt)(password, salt)];
|
|
161
|
-
case 2:
|
|
162
|
-
hash = _a.sent();
|
|
163
|
-
return [2 /*return*/, { salt: salt, hash: hash }];
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
function validatePassword(password, passwordHash, salt) {
|
|
169
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
170
|
-
var hashCandidate;
|
|
171
|
-
return __generator(this, function (_a) {
|
|
172
|
-
switch (_a.label) {
|
|
173
|
-
case 0: return [4 /*yield*/, (0, BcryptUtils_1.encrypt)(password, salt)];
|
|
174
|
-
case 1:
|
|
175
|
-
hashCandidate = _a.sent();
|
|
176
|
-
return [2 /*return*/, hashCandidate === passwordHash];
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Checks if provided role has permission to access route
|
|
3
|
-
* based on its permissions.
|
|
4
|
-
*
|
|
5
|
-
* @param roles logged in user role(s)
|
|
6
|
-
* @param rolePermissions map containing permissions by role
|
|
7
|
-
* @param routePermissions permission(s) required by route
|
|
8
|
-
* @returns
|
|
9
|
-
*/
|
|
10
|
-
export declare function hasValidPermissions(roles: string[], rolePermissions: {
|
|
11
|
-
[x: string]: string[];
|
|
12
|
-
}, routePermissions: string[]): boolean;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.hasValidPermissions = hasValidPermissions;
|
|
4
|
-
var flink_1 = require("@flink-app/flink");
|
|
5
|
-
/**
|
|
6
|
-
* Checks if provided role has permission to access route
|
|
7
|
-
* based on its permissions.
|
|
8
|
-
*
|
|
9
|
-
* @param roles logged in user role(s)
|
|
10
|
-
* @param rolePermissions map containing permissions by role
|
|
11
|
-
* @param routePermissions permission(s) required by route
|
|
12
|
-
* @returns
|
|
13
|
-
*/
|
|
14
|
-
function hasValidPermissions(roles, rolePermissions, routePermissions) {
|
|
15
|
-
if (routePermissions.includes("*")) {
|
|
16
|
-
return roles.length > 0;
|
|
17
|
-
}
|
|
18
|
-
if (routePermissions.length === 0) {
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
var _loop_1 = function (role) {
|
|
22
|
-
var thisRolesPermissions = rolePermissions[role];
|
|
23
|
-
if (!thisRolesPermissions) {
|
|
24
|
-
flink_1.log.warn("Role '".concat(role, "' does not have any permissions defined"));
|
|
25
|
-
return "continue";
|
|
26
|
-
}
|
|
27
|
-
if (thisRolesPermissions.includes("*")) {
|
|
28
|
-
return { value: true };
|
|
29
|
-
}
|
|
30
|
-
if (routePermissions.every(function (routePerm) {
|
|
31
|
-
return thisRolesPermissions.includes(routePerm);
|
|
32
|
-
})) {
|
|
33
|
-
return { value: true };
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
for (var _i = 0, roles_1 = roles; _i < roles_1.length; _i++) {
|
|
37
|
-
var role = roles_1[_i];
|
|
38
|
-
var state_1 = _loop_1(role);
|
|
39
|
-
if (typeof state_1 === "object")
|
|
40
|
-
return state_1.value;
|
|
41
|
-
}
|
|
42
|
-
return false;
|
|
43
|
-
}
|
package/dist/src/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./FlinkJwtAuthPlugin";
|
package/dist/src/index.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./FlinkJwtAuthPlugin"), exports);
|