ltijs
Version:
Easily turn your web application into a LTI 1.3 Learning Tool.
34 lines • 1.74 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.signValue = signValue;
exports.verifySignedValue = verifySignedValue;
const node_crypto_1 = __importDefault(require("node:crypto"));
// Cookie-signing-style HMAC, for values that only this server ever signs and verifies. Unlike the
// RS256 JWTs used elsewhere (state, ltik), there's no third party independently verifying these, so
// there's no need for asymmetric signing. As a side effect, the two are structurally incompatible: an
// HMAC token is never JWT-shaped, so `verifyTokenSignature` rejects it outright, and vice versa.
const HMAC_ALGORITHM = 'sha256';
const SEPARATOR = '.';
function signValue(value, secret) {
const signature = node_crypto_1.default.createHmac(HMAC_ALGORITHM, secret).update(value).digest('base64url');
return `${value}${SEPARATOR}${signature}`;
}
function verifySignedValue(token, secret) {
const separatorIndex = token.lastIndexOf(SEPARATOR);
if (separatorIndex === -1)
return undefined;
const value = token.slice(0, separatorIndex);
const signature = token.slice(separatorIndex + 1);
const expected = node_crypto_1.default.createHmac(HMAC_ALGORITHM, secret).update(value).digest('base64url');
const signatureBuffer = Buffer.from(signature);
const expectedBuffer = Buffer.from(expected);
if (signatureBuffer.length !== expectedBuffer.length)
return undefined;
if (!node_crypto_1.default.timingSafeEqual(signatureBuffer, expectedBuffer))
return undefined;
return value;
}
//# sourceMappingURL=signed-value.js.map