koa-stateless-csrf
Version:
Stateless CSRF support for Koa APIs
77 lines (76 loc) • 2.44 kB
JavaScript
import { timingSafeEqual as y, randomBytes as k } from "crypto";
const a = 32, b = () => k(a), E = (e, n) => e.length === a && n.length === a && y(e, n), O = (e, n) => e.length === a && n.length === a * 2 ? E(e, S(n)) : !1, o = (e, n) => {
const l = e.length;
if (l !== n.length)
throw new Error("Lengths of slices are not equal");
for (let f = 0; f < l; ++f)
e[f] ^= n[f];
}, C = (e) => {
if (e.length !== a)
throw new Error("Invalid token length");
const n = Buffer.allocUnsafe(a * 2);
e.copy(n);
const l = k(a);
return l.copy(n, a), o(n.subarray(0, a), l), n;
}, S = (e) => {
if (e.length !== a * 2)
throw new Error("Invalid token length");
const n = e.subarray(0, a), l = e.subarray(a);
return o(n, l), n;
}, v = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS", "TRACE"]), B = (e) => {
e.throw(
400,
"The calling origin is not allowed to perform this request",
{ name: "CsrfError" }
);
}, i = (e) => {
e.throw(
400,
"The CSRF token in the cookie doesn't match the one received in a header",
{ name: "CsrfError" }
);
}, R = (e) => {
const n = (e == null ? void 0 : e.cookieName) ?? "csrf_token", l = (e == null ? void 0 : e.headerName) ?? "X-CSRF-Token", f = (r) => {
const t = r.get(l);
return t ? t === "fetch" ? "fetch" : Buffer.from(t, "base64") : null;
}, u = (r, t) => {
r.set(l, C(t).toString("base64"));
}, d = (r, t) => {
r.cookies.set(
n,
t.toString("base64"),
{
path: "/",
...e == null ? void 0 : e.cookieOptions,
httpOnly: !0,
signed: !1
}
);
}, T = (r) => {
const t = b();
return d(r, t), t;
}, g = (r) => {
let s = Buffer.from(r.cookies.get(n) ?? "", "base64").subarray(0, a), c = !1;
return s.length !== a && (s = T(r), c = !0), [s, c];
};
return async (r, t) => {
(e != null && e.disableWithoutOrigin || e != null && e.allowedOrigins) && r.vary("Origin"), r.vary("Cookie");
const s = r.get("Origin");
if (!s && (e != null && e.disableWithoutOrigin))
return t();
if (e != null && e.allowedOrigins && !e.allowedOrigins.includes(s))
return B(r);
const c = f(r);
if (c === "fetch") {
const [w] = g(r);
u(r, w);
}
if (v.has(r.method))
return t();
const [h, m] = g(r);
return m || !Buffer.isBuffer(c) || !O(h, c) ? (u(r, h), i(r)) : t();
};
};
export {
R as csrfMiddleware
};