@flink-app/jwt-auth-plugin 0.11.0 → 0.11.4-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BcryptUtils.js +2 -3
- package/dist/FlinkJwtAuthPlugin.js +20 -21
- package/dist/PermissionValidator.js +2 -3
- package/dist/index.js +5 -1
- package/dist/spec/FlinkJwtAuthPlugin.spec.d.ts +1 -0
- package/dist/spec/FlinkJwtAuthPlugin.spec.js +193 -0
- package/dist/spec/PermissionValidator.spec.d.ts +1 -0
- package/dist/spec/PermissionValidator.spec.js +45 -0
- package/dist/src/BcryptUtils.d.ts +2 -0
- package/dist/src/BcryptUtils.js +27 -0
- package/dist/src/FlinkJwtAuthPlugin.d.ts +41 -0
- package/dist/src/FlinkJwtAuthPlugin.js +180 -0
- package/dist/src/PermissionValidator.d.ts +12 -0
- package/dist/src/PermissionValidator.js +43 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +17 -0
- package/package.json +30 -33
package/dist/BcryptUtils.js
CHANGED
|
@@ -3,7 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.encrypt = encrypt;
|
|
7
|
+
exports.genSalt = genSalt;
|
|
7
8
|
var bcrypt_1 = __importDefault(require("bcrypt"));
|
|
8
9
|
function encrypt(password, salt) {
|
|
9
10
|
return new Promise(function (resolve, reject) {
|
|
@@ -14,7 +15,6 @@ function encrypt(password, salt) {
|
|
|
14
15
|
});
|
|
15
16
|
});
|
|
16
17
|
}
|
|
17
|
-
exports.encrypt = encrypt;
|
|
18
18
|
function genSalt(rounds) {
|
|
19
19
|
if (rounds === void 0) { rounds = 10; }
|
|
20
20
|
return new Promise(function (resolve, reject) {
|
|
@@ -25,4 +25,3 @@ function genSalt(rounds) {
|
|
|
25
25
|
});
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
|
-
exports.genSalt = genSalt;
|
|
@@ -20,12 +20,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
20
20
|
});
|
|
21
21
|
};
|
|
22
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;
|
|
24
|
-
return g =
|
|
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
25
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
26
|
function step(op) {
|
|
27
27
|
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (_) try {
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
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
30
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
31
|
switch (op[0]) {
|
|
@@ -50,7 +50,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
50
50
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
51
51
|
};
|
|
52
52
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
-
exports.jwtAuthPlugin =
|
|
53
|
+
exports.jwtAuthPlugin = jwtAuthPlugin;
|
|
54
54
|
var flink_1 = require("@flink-app/flink");
|
|
55
55
|
var jwt_simple_1 = __importDefault(require("jwt-simple"));
|
|
56
56
|
var BcryptUtils_1 = require("./BcryptUtils");
|
|
@@ -85,13 +85,12 @@ function jwtAuthPlugin(_a) {
|
|
|
85
85
|
validatePassword: validatePassword,
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
|
-
|
|
89
|
-
function
|
|
90
|
-
var secret = _a.secret, algo = _a.algo, getUser = _a.getUser;
|
|
91
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
88
|
+
function authenticateRequest(req_1, routePermissions_1, rolePermissions_1, _a) {
|
|
89
|
+
return __awaiter(this, arguments, void 0, function (req, routePermissions, rolePermissions, _b) {
|
|
92
90
|
var token, decodedToken, permissionsArr, validPerms, user;
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
var secret = _b.secret, algo = _b.algo, getUser = _b.getUser;
|
|
92
|
+
return __generator(this, function (_c) {
|
|
93
|
+
switch (_c.label) {
|
|
95
94
|
case 0:
|
|
96
95
|
token = getTokenFromReq(req);
|
|
97
96
|
if (!token) return [3 /*break*/, 2];
|
|
@@ -100,7 +99,7 @@ function authenticateRequest(req, routePermissions, rolePermissions, _a) {
|
|
|
100
99
|
decodedToken = jwt_simple_1.default.decode(token, secret, false, algo);
|
|
101
100
|
}
|
|
102
101
|
catch (err) {
|
|
103
|
-
flink_1.log.debug("Failed to decode token: "
|
|
102
|
+
flink_1.log.debug("Failed to decode token: ".concat(err));
|
|
104
103
|
decodedToken = null;
|
|
105
104
|
}
|
|
106
105
|
if (!decodedToken) return [3 /*break*/, 2];
|
|
@@ -108,14 +107,14 @@ function authenticateRequest(req, routePermissions, rolePermissions, _a) {
|
|
|
108
107
|
? routePermissions
|
|
109
108
|
: [routePermissions];
|
|
110
109
|
if (permissionsArr && permissionsArr.length > 0) {
|
|
111
|
-
validPerms = PermissionValidator_1.hasValidPermissions(decodedToken.roles || [], rolePermissions, permissionsArr);
|
|
110
|
+
validPerms = (0, PermissionValidator_1.hasValidPermissions)(decodedToken.roles || [], rolePermissions, permissionsArr);
|
|
112
111
|
if (!validPerms) {
|
|
113
112
|
return [2 /*return*/, false];
|
|
114
113
|
}
|
|
115
114
|
}
|
|
116
115
|
return [4 /*yield*/, getUser(decodedToken)];
|
|
117
116
|
case 1:
|
|
118
|
-
user =
|
|
117
|
+
user = _c.sent();
|
|
119
118
|
req.user = user;
|
|
120
119
|
return [2 /*return*/, true];
|
|
121
120
|
case 2: return [2 /*return*/, false];
|
|
@@ -131,10 +130,10 @@ function getTokenFromReq(req) {
|
|
|
131
130
|
}
|
|
132
131
|
return;
|
|
133
132
|
}
|
|
134
|
-
function createToken(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return __generator(this, function (
|
|
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) {
|
|
138
137
|
if (!payload) {
|
|
139
138
|
throw new Error("Cannot create token - payload is missing");
|
|
140
139
|
}
|
|
@@ -152,13 +151,13 @@ function createPasswordHashAndSalt(password, passwordPolicy) {
|
|
|
152
151
|
switch (_a.label) {
|
|
153
152
|
case 0:
|
|
154
153
|
if (!passwordPolicy.test(password)) {
|
|
155
|
-
flink_1.log.debug("Password does not match password policy '"
|
|
154
|
+
flink_1.log.debug("Password does not match password policy '".concat(passwordPolicy, "'"));
|
|
156
155
|
return [2 /*return*/, null];
|
|
157
156
|
}
|
|
158
|
-
return [4 /*yield*/, BcryptUtils_1.genSalt(10)];
|
|
157
|
+
return [4 /*yield*/, (0, BcryptUtils_1.genSalt)(10)];
|
|
159
158
|
case 1:
|
|
160
159
|
salt = _a.sent();
|
|
161
|
-
return [4 /*yield*/, BcryptUtils_1.encrypt(password, salt)];
|
|
160
|
+
return [4 /*yield*/, (0, BcryptUtils_1.encrypt)(password, salt)];
|
|
162
161
|
case 2:
|
|
163
162
|
hash = _a.sent();
|
|
164
163
|
return [2 /*return*/, { salt: salt, hash: hash }];
|
|
@@ -171,7 +170,7 @@ function validatePassword(password, passwordHash, salt) {
|
|
|
171
170
|
var hashCandidate;
|
|
172
171
|
return __generator(this, function (_a) {
|
|
173
172
|
switch (_a.label) {
|
|
174
|
-
case 0: return [4 /*yield*/, BcryptUtils_1.encrypt(password, salt)];
|
|
173
|
+
case 0: return [4 /*yield*/, (0, BcryptUtils_1.encrypt)(password, salt)];
|
|
175
174
|
case 1:
|
|
176
175
|
hashCandidate = _a.sent();
|
|
177
176
|
return [2 /*return*/, hashCandidate === passwordHash];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.hasValidPermissions =
|
|
3
|
+
exports.hasValidPermissions = hasValidPermissions;
|
|
4
4
|
var flink_1 = require("@flink-app/flink");
|
|
5
5
|
/**
|
|
6
6
|
* Checks if provided role has permission to access route
|
|
@@ -21,7 +21,7 @@ function hasValidPermissions(roles, rolePermissions, routePermissions) {
|
|
|
21
21
|
var _loop_1 = function (role) {
|
|
22
22
|
var thisRolesPermissions = rolePermissions[role];
|
|
23
23
|
if (!thisRolesPermissions) {
|
|
24
|
-
flink_1.log.warn("Role '"
|
|
24
|
+
flink_1.log.warn("Role '".concat(role, "' does not have any permissions defined"));
|
|
25
25
|
return "continue";
|
|
26
26
|
}
|
|
27
27
|
if (thisRolesPermissions.includes("*")) {
|
|
@@ -41,4 +41,3 @@ function hasValidPermissions(roles, rolePermissions, routePermissions) {
|
|
|
41
41
|
}
|
|
42
42
|
return false;
|
|
43
43
|
}
|
|
44
|
-
exports.hasValidPermissions = hasValidPermissions;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
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);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,193 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
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;
|
|
@@ -0,0 +1,180 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
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;
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./FlinkJwtAuthPlugin";
|
|
@@ -0,0 +1,17 @@
|
|
|
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);
|
package/package.json
CHANGED
|
@@ -1,35 +1,32 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
"typescript": "^4.2.4"
|
|
33
|
-
},
|
|
34
|
-
"gitHead": "3869def3e7e7e7105373ad31bc23a8ed68108015"
|
|
2
|
+
"name": "@flink-app/jwt-auth-plugin",
|
|
3
|
+
"version": "0.11.4-next.0",
|
|
4
|
+
"description": "Flink plugin for JWT auth",
|
|
5
|
+
"author": "joel@frost.se",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"bcrypt": "^5.0.1",
|
|
17
|
+
"jwt-simple": "^0.5.6"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@flink-app/flink": "^0.11.4-next.0",
|
|
21
|
+
"@types/bcrypt": "^5.0.0",
|
|
22
|
+
"@types/jasmine": "^3.7.1",
|
|
23
|
+
"@types/node": "^22.10.1",
|
|
24
|
+
"jasmine": "^3.7.0",
|
|
25
|
+
"jasmine-spec-reporter": "^7.0.0",
|
|
26
|
+
"nodemon": "^2.0.7",
|
|
27
|
+
"ts-node": "^10.9.2",
|
|
28
|
+
"tsc-watch": "^6.2.1",
|
|
29
|
+
"typescript": "5.6.2"
|
|
30
|
+
},
|
|
31
|
+
"gitHead": "6a44df1b6601c86ea3402750b939784d003202c3"
|
|
35
32
|
}
|