UNPKG

@taxum/cookie

Version:
76 lines 2.5 kB
import { createHmac } from "node:crypto"; const BASE64_DIGEST_LEN = 44; /** * A child cookie jar that authenticates its cookies. * * A _signed_ child jar signs all the cookies added to it and verifies cookies * retrieved from it. Any cookies stored in the `SignedJar` are provided * integrity and authenticity. In other words, clients cannot tamper with the * contents of a cookie, nor can they fabricate cookie values, but the data is * visible in plaintext. */ export class SignedJar { parent; key; /** * @internal */ constructor(parent, key) { this.parent = parent; this.key = key; } /** * Returns a {@link Cookie} with the name `name` from the parent jar. * * It verifies the authenticity and integrity of the cookie's value, * returning a `Cookie` with the authenticated value. If the cookie cannot * be found, or the cookie fails to verify, `null` is returned. * * @see {@link CookieJar.get} */ get(name) { const cookie = this.parent.get(name); return cookie ? this.verify(cookie) : null; } /** * Adds a {@link Cookie} to the parent jar. * * The cookie's value is signed assuring integrity and authenticity. * * @see {@link CookieJar.add} */ add(cookie) { this.parent.add(this.sign(cookie)); } /** * Removes a {@link Cookie} from the parent jar. * * For correct removal, the passed in `cookie` must contain the same `path` * and `domain` as the cookie that was initially set. * * @see {@link CookieJar.remove} */ remove(cookie) { this.parent.remove(cookie); } sign(cookie) { const hmac = createHmac("sha256", this.key); hmac.update(cookie.value); const signature = hmac.digest("base64"); return cookie.withValue(`${signature}${cookie.value}`); } verify(cookie) { const value = this.verifyValue(cookie.value); return value ? cookie.withValue(value) : null; } verifyValue(cookieValue) { const signature = cookieValue.slice(0, BASE64_DIGEST_LEN); const value = cookieValue.slice(BASE64_DIGEST_LEN); const digest = Buffer.from(signature, "base64"); const hmac = createHmac("sha256", this.key); hmac.update(value); const actualDigest = hmac.digest(); return digest.equals(actualDigest) ? value : null; } } //# sourceMappingURL=signed.js.map