UNPKG

koa-stateless-csrf

Version:
2 lines (1 loc) 1.86 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("crypto"),a=32,w=()=>o.randomBytes(a),b=(e,n)=>e.length===a&&n.length===a&&o.timingSafeEqual(e,n),O=(e,n)=>e.length===a&&n.length===a*2?b(e,C(n)):!1,k=(e,n)=>{const l=e.length;if(l!==n.length)throw new Error("Lengths of slices are not equal");for(let s=0;s<l;++s)e[s]^=n[s]},E=e=>{if(e.length!==a)throw new Error("Invalid token length");const n=Buffer.allocUnsafe(a*2);e.copy(n);const l=o.randomBytes(a);return l.copy(n,a),k(n.subarray(0,a),l),n},C=e=>{if(e.length!==a*2)throw new Error("Invalid token length");const n=e.subarray(0,a),l=e.subarray(a);return k(n,l),n},S=new Set(["GET","HEAD","OPTIONS","TRACE"]),v=e=>{e.throw(400,"The calling origin is not allowed to perform this request",{name:"CsrfError"})},h=e=>{e.throw(400,"The CSRF token in the cookie doesn't match the one received in a header",{name:"CsrfError"})},B=e=>{const n=(e==null?void 0:e.cookieName)??"csrf_token",l=(e==null?void 0:e.headerName)??"X-CSRF-Token",s=r=>{const t=r.get(l);return t?t==="fetch"?"fetch":Buffer.from(t,"base64"):null},u=(r,t)=>{r.set(l,E(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=w();return d(r,t),t},g=r=>{let f=Buffer.from(r.cookies.get(n)??"","base64").subarray(0,a),c=!1;return f.length!==a&&(f=T(r),c=!0),[f,c]};return async(r,t)=>{(e!=null&&e.disableWithoutOrigin||e!=null&&e.allowedOrigins)&&r.vary("Origin"),r.vary("Cookie");const f=r.get("Origin");if(!f&&(e!=null&&e.disableWithoutOrigin))return t();if(e!=null&&e.allowedOrigins&&!e.allowedOrigins.includes(f))return v(r);const c=s(r);if(c==="fetch"){const[y]=g(r);u(r,y)}if(S.has(r.method))return t();const[i,m]=g(r);return m||!Buffer.isBuffer(c)||!O(i,c)?(u(r,i),h(r)):t()}};exports.csrfMiddleware=B;