UNPKG

@designerstrust/remix-utils

Version:

This package contains simple utility functions to use with [Remix.run](https://remix.run).

77 lines (76 loc) 3.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.verifyAuthenticityToken = exports.createAuthenticityToken = void 0; const uuid_1 = require("uuid"); const responses_1 = require("./responses"); /** * Create a random string in Base64 to be used as an authenticity token for * CSRF protection. You should run this on the `root.tsx` loader only. * @example * let token = createAuthenticityToken(session); // create and set in session * return json({ ...otherData, csrf: token }); // return the token in the data * @example * // create and set in session with the key `csrf-token` * let token = createAuthenticityToken(session, "csrfToken"); * return json({ ...otherData, csrf: token }); // return the token in the data */ function createAuthenticityToken(session, sessionKey = "csrf") { let token = session.get(sessionKey); if (typeof token === "string") return token; let newToken = (0, uuid_1.v4)(); session.set(sessionKey, newToken); return newToken; } exports.createAuthenticityToken = createAuthenticityToken; /** * Verify if a request and session has a valid CSRF token. * @example * let action: ActionFunction = async ({ request }) => { * let session = await getSession(request.headers.get("Cookie")); * await verifyAuthenticityToken(request, session); * // the request is authenticated and you can do anything here * } * @example * let action: ActionFunction = async ({ request }) => { * let session = await getSession(request.headers.get("Cookie")); * await verifyAuthenticityToken(request, session, "csrfToken"); * // the request is authenticated and you can do anything here * } * @example * let action: ActionFunction = async ({ request }) => { * let session = await getSession(request.headers.get("Cookie")); * let formData = await unstable_parseMultipartFormData(request, uploadHandler); * await verifyAuthenticityToken(formData, session); * // the request is authenticated and you can do anything here * } */ async function verifyAuthenticityToken(data, session, sessionKey = "csrf") { if (data instanceof Request && data.bodyUsed) { throw new Error("The body of the request was read before calling verifyAuthenticityToken. Ensure you clone it before reading it."); } // We clone the request to ensure we don't modify the original request. // This allow us to parse the body of the request and let the original request // still be used and parsed without errors. let formData = data instanceof FormData ? data : await data.clone().formData(); // if the session doesn't have a csrf token, throw an error if (!session.has(sessionKey)) { throw (0, responses_1.unprocessableEntity)({ message: "Can't find CSRF token in session.", }); } // if the body doesn't have a csrf token, throw an error if (!formData.get(sessionKey)) { throw (0, responses_1.unprocessableEntity)({ message: "Can't find CSRF token in body.", }); } // if the body csrf token doesn't match the session csrf token, throw an // error if (formData.get(sessionKey) !== session.get(sessionKey)) { throw (0, responses_1.unprocessableEntity)({ message: "Can't verify CSRF token authenticity.", }); } } exports.verifyAuthenticityToken = verifyAuthenticityToken;