UNPKG

@linkedmink/passport-mutual-key-challenge

Version:

Implements a Passport strategy to authenticate the public key of a user by issuing a dynamic generated challenge

85 lines 4.16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MutualKeyChallengeStrategy = void 0; const passport_strategy_1 = require("passport-strategy"); const MessageVerifier_1 = require("./MessageVerifier"); const MutualKeyChallengeOptions_1 = require("./MutualKeyChallengeOptions"); const TypeCheck_1 = require("./Helpers/TypeCheck"); const Types_1 = require("./Types"); class MutualKeyChallengeStrategy extends passport_strategy_1.Strategy { constructor(options) { super(); this.options = { ...(0, MutualKeyChallengeOptions_1.getDefaultOptions)(), ...options, }; this.verifier = new MessageVerifier_1.MessageVerifier(this.options.serverKey, this.options.cryptography); } async authenticate(req, options) { const request = this.options.challengeOrResponseFunc(req); if (Types_1.ChallengeError.isType(request)) { return this.error(request); } if ((0, TypeCheck_1.isClientResponse)(request)) { return this.handleChallengeResponse(req, request); } return this.handleChallengeRequest(req, request); } async handleChallengeResponse(req, message) { const user = await this.getUserResult(req, message.userId); if (Types_1.ChallengeError.isType(user)) { return this.error(user); } if (!(await this.verifier.verify(user.publicKey, message.clientResponsed))) { return this.error(new Types_1.ChallengeError("The response could not be verified", Types_1.ChallengeStage.ServerChallenge)); } const challengeGet = this.options.challengeCache.get(message.userId); const challenge = (0, TypeCheck_1.isPromise)(challengeGet) ? await challengeGet : challengeGet; if (!challenge) { return this.error(new Types_1.ChallengeError("Challenge is not initiated or expired", Types_1.ChallengeStage.ServerChallenge)); } if (!challenge.clientChallenged.equals(message.clientResponsed.message)) { return this.error(new Types_1.ChallengeError("Challenge is incorrect", Types_1.ChallengeStage.ServerChallenge)); } this.success(user.user, user.publicKey); } async handleChallengeRequest(req, message) { const user = await this.getUserResult(req, message.userId); if (Types_1.ChallengeError.isType(user)) { return this.error(user); } const decrypted = await this.verifier.decryptAndVerify(user.publicKey, message.clientRequested); if (!decrypted) { return this.error(new Types_1.ChallengeError("The response could not be verified", Types_1.ChallengeStage.ServerChallenge)); } const decryptedMessage = await this.verifier.sign(decrypted); const nonce = this.verifier.getNonce(); const nonceMessage = await this.verifier.encryptAndSign(user.publicKey, nonce); const challengeSet = this.options.challengeCache.set(message.userId, { userId: message.userId, clientChallenged: nonce, requestDateTime: message.requestDateTime, }); if ((0, TypeCheck_1.isPromise)(challengeSet)) { await challengeSet; } const challenge = { clientRequested: decryptedMessage, serverRequested: nonceMessage, }; this.fail(challenge, 401); } async getUserResult(req, userId) { const userResult = this.options.userFunc(req, userId); if (!userResult) { return new Types_1.ChallengeError("No user could be found", Types_1.ChallengeStage.ServerChallenge); } const user = (0, TypeCheck_1.isPromise)(userResult) ? await userResult : userResult; if (!user) { return new Types_1.ChallengeError("No user could be found", Types_1.ChallengeStage.ServerChallenge); } return user; } } exports.MutualKeyChallengeStrategy = MutualKeyChallengeStrategy; //# sourceMappingURL=MutualKeyChallengeStrategy.js.map