kuzzle 2.50.3 → 2.51.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.
|
@@ -46,7 +46,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
46
46
|
* See the License for the specific language governing permissions and
|
|
47
47
|
* limitations under the License.
|
|
48
48
|
*/
|
|
49
|
-
const
|
|
49
|
+
const node_http_1 = require("node:http");
|
|
50
50
|
const Cookie = __importStar(require("cookie"));
|
|
51
51
|
const bluebird_1 = __importDefault(require("bluebird"));
|
|
52
52
|
const lodash_1 = require("lodash");
|
|
@@ -59,6 +59,7 @@ const formatProcessing_1 = __importDefault(require("../../core/auth/formatProces
|
|
|
59
59
|
const user_1 = require("../../model/security/user");
|
|
60
60
|
const apiKey_1 = __importDefault(require("../../model/storage/apiKey"));
|
|
61
61
|
const securityController_1 = __importDefault(require("./securityController"));
|
|
62
|
+
const securityError = kerror.wrap("security", "token");
|
|
62
63
|
class AuthController extends baseController_1.NativeController {
|
|
63
64
|
/**
|
|
64
65
|
* @param {Kuzzle} kuzzle
|
|
@@ -87,7 +88,7 @@ class AuthController extends baseController_1.NativeController {
|
|
|
87
88
|
"validateMyCredentials",
|
|
88
89
|
]);
|
|
89
90
|
this.anonymousId = null;
|
|
90
|
-
this.logger =
|
|
91
|
+
this.logger = globalThis.kuzzle.log.child("api:controllers:auth");
|
|
91
92
|
}
|
|
92
93
|
/**
|
|
93
94
|
* Controller initialization: we need the anonymous user identifier for the
|
|
@@ -96,7 +97,7 @@ class AuthController extends baseController_1.NativeController {
|
|
|
96
97
|
* @returns {Promise}
|
|
97
98
|
*/
|
|
98
99
|
async init() {
|
|
99
|
-
const anonymous = await
|
|
100
|
+
const anonymous = await globalThis.kuzzle.ask("core:security:user:anonymous:get");
|
|
100
101
|
this.anonymousId = anonymous._id;
|
|
101
102
|
}
|
|
102
103
|
async createToken(request) {
|
|
@@ -191,24 +192,24 @@ class AuthController extends baseController_1.NativeController {
|
|
|
191
192
|
* @returns {Promise<object>}
|
|
192
193
|
*/
|
|
193
194
|
async logout(request) {
|
|
194
|
-
if (!
|
|
195
|
+
if (!globalThis.kuzzle.config.http.cookieAuthentication ||
|
|
195
196
|
!request.getBoolean("cookieAuth")) {
|
|
196
197
|
this.assertIsAuthenticated(request);
|
|
197
198
|
}
|
|
198
|
-
if (
|
|
199
|
+
if (globalThis.kuzzle.config.internal.notifiableProtocols.includes(request.context.connection.protocol)) {
|
|
199
200
|
// Unlink connection so the connection will not be notified when the token expires.
|
|
200
|
-
|
|
201
|
+
globalThis.kuzzle.tokenManager.unlink(request.context.token, request.context.connection.id);
|
|
201
202
|
}
|
|
202
203
|
if (request.context.user._id !== this.anonymousId) {
|
|
203
204
|
if (request.getBoolean("global")) {
|
|
204
|
-
await
|
|
205
|
+
await globalThis.kuzzle.ask("core:security:token:deleteByKuid", request.getKuid(), { keepApiKeys: true });
|
|
205
206
|
}
|
|
206
207
|
else if (request.context.token &&
|
|
207
208
|
request.context.token.type !== "apiKey") {
|
|
208
|
-
await
|
|
209
|
+
await globalThis.kuzzle.ask("core:security:token:delete", request.context.token);
|
|
209
210
|
}
|
|
210
211
|
}
|
|
211
|
-
if (
|
|
212
|
+
if (globalThis.kuzzle.config.http.cookieAuthentication &&
|
|
212
213
|
request.getBoolean("cookieAuth")) {
|
|
213
214
|
request.response.configure({
|
|
214
215
|
headers: {
|
|
@@ -234,7 +235,7 @@ class AuthController extends baseController_1.NativeController {
|
|
|
234
235
|
// otherwise we should send a normal response because
|
|
235
236
|
// even if the SDK / Browser can handle the cookie,
|
|
236
237
|
// Kuzzle would not be capable of doing anything with it
|
|
237
|
-
if (
|
|
238
|
+
if (globalThis.kuzzle.config.http.cookieAuthentication &&
|
|
238
239
|
request.getBoolean("cookieAuth")) {
|
|
239
240
|
// Here we are not sending auth token when cookieAuth is set to true
|
|
240
241
|
// This allow us to detect if kuzzle does support cookie as auth token directly from the SDK
|
|
@@ -262,7 +263,7 @@ class AuthController extends baseController_1.NativeController {
|
|
|
262
263
|
*/
|
|
263
264
|
async login(request) {
|
|
264
265
|
const strategy = request.getString("strategy");
|
|
265
|
-
const passportRequest = new
|
|
266
|
+
const passportRequest = new node_http_1.IncomingMessage(null);
|
|
266
267
|
// Even in http, the url and the method are not pushed back to the request object
|
|
267
268
|
// set some arbitrary values to get a pseudo-valid object.
|
|
268
269
|
passportRequest.url = `/login?strategy=${strategy}`;
|
|
@@ -278,10 +279,10 @@ class AuthController extends baseController_1.NativeController {
|
|
|
278
279
|
passportRequest.rawHeaders.push(passportRequest.headers[h]);
|
|
279
280
|
}
|
|
280
281
|
passportRequest.original = request;
|
|
281
|
-
if (!(0, safeObject_1.has)(
|
|
282
|
+
if (!(0, safeObject_1.has)(globalThis.kuzzle.pluginsManager.strategies, strategy)) {
|
|
282
283
|
throw kerror.get("security", "credentials", "unknown_strategy", strategy);
|
|
283
284
|
}
|
|
284
|
-
const content = await
|
|
285
|
+
const content = await globalThis.kuzzle.passport.authenticate(passportRequest, strategy);
|
|
285
286
|
// do not trigger the "auth:strategyAutenticated" pipe if the result is
|
|
286
287
|
// not a User object, i.e. if we are a intermediate step of a multi-step
|
|
287
288
|
// authentication strategy
|
|
@@ -300,7 +301,7 @@ class AuthController extends baseController_1.NativeController {
|
|
|
300
301
|
if (request.input.args.expiresIn) {
|
|
301
302
|
options.expiresIn = request.input.args.expiresIn;
|
|
302
303
|
}
|
|
303
|
-
const existingToken =
|
|
304
|
+
const existingToken = globalThis.kuzzle.tokenManager.getConnectedUserToken(authResponse.content._id, request.context.connection.id);
|
|
304
305
|
/**
|
|
305
306
|
* If a previous token from the same User is linked to this connection
|
|
306
307
|
* and the token is either an API Key or an infinite duration token
|
|
@@ -313,11 +314,11 @@ class AuthController extends baseController_1.NativeController {
|
|
|
313
314
|
}
|
|
314
315
|
const token = await this.ask("core:security:token:create", authResponse.content, options);
|
|
315
316
|
if (existingToken) {
|
|
316
|
-
|
|
317
|
+
globalThis.kuzzle.tokenManager.refresh(existingToken, token);
|
|
317
318
|
}
|
|
318
|
-
if (
|
|
319
|
+
if (globalThis.kuzzle.config.internal.notifiableProtocols.includes(request.context.connection.protocol)) {
|
|
319
320
|
// Link the connection with the token, this way the connection can be notified when the token has expired.
|
|
320
|
-
|
|
321
|
+
globalThis.kuzzle.tokenManager.link(token, request.context.connection.id);
|
|
321
322
|
}
|
|
322
323
|
return this._sendToken(token, request);
|
|
323
324
|
}
|
|
@@ -338,8 +339,8 @@ class AuthController extends baseController_1.NativeController {
|
|
|
338
339
|
promises.push(bluebird_1.default.resolve([]));
|
|
339
340
|
}
|
|
340
341
|
else {
|
|
341
|
-
for (const strategy of
|
|
342
|
-
const existsMethod =
|
|
342
|
+
for (const strategy of globalThis.kuzzle.pluginsManager.listStrategies()) {
|
|
343
|
+
const existsMethod = globalThis.kuzzle.pluginsManager.getStrategyMethod(strategy, "exists");
|
|
343
344
|
promises.push(existsMethod(request, userId, strategy)
|
|
344
345
|
.then((exists) => (exists ? strategy : null))
|
|
345
346
|
.catch((err) => wrapPluginError(err)));
|
|
@@ -371,7 +372,7 @@ class AuthController extends baseController_1.NativeController {
|
|
|
371
372
|
*/
|
|
372
373
|
async checkToken(request) {
|
|
373
374
|
let token = "";
|
|
374
|
-
if (
|
|
375
|
+
if (globalThis.kuzzle.config.http.cookieAuthentication &&
|
|
375
376
|
request.getBoolean("cookieAuth")) {
|
|
376
377
|
token = request.input.jwt;
|
|
377
378
|
}
|
|
@@ -414,7 +415,7 @@ class AuthController extends baseController_1.NativeController {
|
|
|
414
415
|
* @returns {Promise.<string[]>}
|
|
415
416
|
*/
|
|
416
417
|
getStrategies() {
|
|
417
|
-
return bluebird_1.default.resolve(
|
|
418
|
+
return bluebird_1.default.resolve(globalThis.kuzzle.pluginsManager.listStrategies());
|
|
418
419
|
}
|
|
419
420
|
/**
|
|
420
421
|
* @param {KuzzleRequest} request
|
|
@@ -424,7 +425,7 @@ class AuthController extends baseController_1.NativeController {
|
|
|
424
425
|
this.assertIsAuthenticated(request);
|
|
425
426
|
const userId = request.getKuid(), strategy = request.getString("strategy"), credentials = request.getBody();
|
|
426
427
|
this.assertIsStrategyRegistered(strategy);
|
|
427
|
-
const createMethod =
|
|
428
|
+
const createMethod = globalThis.kuzzle.pluginsManager.getStrategyMethod(strategy, "create"), validateMethod = globalThis.kuzzle.pluginsManager.getStrategyMethod(strategy, "validate");
|
|
428
429
|
return validateMethod(request, credentials, userId, strategy, false)
|
|
429
430
|
.then(() => createMethod(request, credentials, userId, strategy))
|
|
430
431
|
.catch((err) => wrapPluginError(err));
|
|
@@ -437,7 +438,7 @@ class AuthController extends baseController_1.NativeController {
|
|
|
437
438
|
this.assertIsAuthenticated(request);
|
|
438
439
|
const userId = request.getKuid(), strategy = request.getString("strategy"), credentials = request.getBody();
|
|
439
440
|
this.assertIsStrategyRegistered(strategy);
|
|
440
|
-
const updateMethod =
|
|
441
|
+
const updateMethod = globalThis.kuzzle.pluginsManager.getStrategyMethod(request.input.args.strategy, "update"), validateMethod = globalThis.kuzzle.pluginsManager.getStrategyMethod(request.input.args.strategy, "validate");
|
|
441
442
|
return validateMethod(request, credentials, userId, strategy, true)
|
|
442
443
|
.then(() => updateMethod(request, credentials, userId, strategy))
|
|
443
444
|
.catch((err) => wrapPluginError(err));
|
|
@@ -450,7 +451,7 @@ class AuthController extends baseController_1.NativeController {
|
|
|
450
451
|
this.assertIsAuthenticated(request);
|
|
451
452
|
const userId = request.getKuid(), strategy = request.getString("strategy");
|
|
452
453
|
this.assertIsStrategyRegistered(strategy);
|
|
453
|
-
const existsMethod =
|
|
454
|
+
const existsMethod = globalThis.kuzzle.pluginsManager.getStrategyMethod(strategy, "exists");
|
|
454
455
|
return existsMethod(request, userId, strategy).catch((err) => wrapPluginError(err));
|
|
455
456
|
}
|
|
456
457
|
/**
|
|
@@ -461,7 +462,7 @@ class AuthController extends baseController_1.NativeController {
|
|
|
461
462
|
this.assertIsAuthenticated(request);
|
|
462
463
|
const userId = request.getKuid(), strategy = request.getString("strategy"), credentials = request.getBody();
|
|
463
464
|
this.assertIsStrategyRegistered(strategy);
|
|
464
|
-
const validateMethod =
|
|
465
|
+
const validateMethod = globalThis.kuzzle.pluginsManager.getStrategyMethod(strategy, "validate");
|
|
465
466
|
return validateMethod(request, credentials, userId, strategy, false).catch((err) => wrapPluginError(err));
|
|
466
467
|
}
|
|
467
468
|
/**
|
|
@@ -472,7 +473,7 @@ class AuthController extends baseController_1.NativeController {
|
|
|
472
473
|
this.assertIsAuthenticated(request);
|
|
473
474
|
const userId = request.getKuid(), strategy = request.getString("strategy");
|
|
474
475
|
this.assertIsStrategyRegistered(strategy);
|
|
475
|
-
const deleteMethod =
|
|
476
|
+
const deleteMethod = globalThis.kuzzle.pluginsManager.getStrategyMethod(strategy, "delete");
|
|
476
477
|
return deleteMethod(request, userId, strategy)
|
|
477
478
|
.then(() => ({ acknowledged: true }))
|
|
478
479
|
.catch((err) => wrapPluginError(err));
|
|
@@ -485,10 +486,10 @@ class AuthController extends baseController_1.NativeController {
|
|
|
485
486
|
this.assertIsAuthenticated(request);
|
|
486
487
|
const userId = request.getKuid(), strategy = request.getString("strategy");
|
|
487
488
|
this.assertIsStrategyRegistered(strategy);
|
|
488
|
-
if (!
|
|
489
|
+
if (!globalThis.kuzzle.pluginsManager.hasStrategyMethod(strategy, "getInfo")) {
|
|
489
490
|
return bluebird_1.default.resolve({});
|
|
490
491
|
}
|
|
491
|
-
const getInfoMethod =
|
|
492
|
+
const getInfoMethod = globalThis.kuzzle.pluginsManager.getStrategyMethod(strategy, "getInfo");
|
|
492
493
|
return getInfoMethod(request, userId, strategy).catch((err) => wrapPluginError(err));
|
|
493
494
|
}
|
|
494
495
|
/**
|
|
@@ -496,6 +497,25 @@ class AuthController extends baseController_1.NativeController {
|
|
|
496
497
|
*/
|
|
497
498
|
async refreshToken(request) {
|
|
498
499
|
this.assertIsAuthenticated(request);
|
|
500
|
+
const strategy = request.input.args?.strategy;
|
|
501
|
+
if (request.input.args?.strategy) {
|
|
502
|
+
try {
|
|
503
|
+
const refreshTokenMethod = globalThis.kuzzle.pluginsManager.getStrategyMethod(strategy, "refreshToken");
|
|
504
|
+
await refreshTokenMethod(request);
|
|
505
|
+
}
|
|
506
|
+
catch (err) {
|
|
507
|
+
/**
|
|
508
|
+
* Every strategies does not implement a standard way of returning errors.
|
|
509
|
+
* Which mean we cannot properly catch any errors in the catch block.
|
|
510
|
+
* Meaning if we arrive here, the refresh token did not work as planned
|
|
511
|
+
* We can safely ensure that the user refresh token is not active anymore
|
|
512
|
+
*/
|
|
513
|
+
this.logger.error(`Error while refreshing the token with the strategy ${strategy} with ERROR: ${err}`);
|
|
514
|
+
// Adding some debug information to better known our target here.
|
|
515
|
+
this.logger.debug(`Error when refreshing token with request: ${JSON.stringify(request)}`);
|
|
516
|
+
throw securityError.get("refresh_forbidden", request.context.token.jwt);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
499
519
|
const token = await this.ask("core:security:token:refresh", request.context.user, request.context.token, request.input.args.expiresIn);
|
|
500
520
|
return this._sendToken(token, request);
|
|
501
521
|
}
|
package/dist/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kuzzle",
|
|
3
3
|
"author": "The Kuzzle Team <support@kuzzle.io>",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.51.0",
|
|
5
5
|
"description": "Kuzzle is an open-source solution that handles all the data management through a secured API, with a large choice of protocols.",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "rm -Rf ./dist && tsc && node ./bin/copy-protobuf.js",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kuzzle",
|
|
3
3
|
"author": "The Kuzzle Team <support@kuzzle.io>",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.51.0",
|
|
5
5
|
"description": "Kuzzle is an open-source solution that handles all the data management through a secured API, with a large choice of protocols.",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "rm -Rf ./dist && tsc && node ./bin/copy-protobuf.js",
|