fix: csrf with get server side props
This commit is contained in:
parent
48ef3224fc
commit
5b8c41c203
|
@ -2,6 +2,7 @@ import type { DehydratedState } from "@tanstack/react-query";
|
|||
import classNames from "classnames";
|
||||
import type { GetServerSideProps, InferGetServerSidePropsType } from "next";
|
||||
import Link from "next/link";
|
||||
import { setCsrfToken } from "pages/api/auth/csrf";
|
||||
import { Toaster } from "react-hot-toast";
|
||||
import type { z } from "zod";
|
||||
|
||||
|
@ -274,6 +275,7 @@ export type UserPageProps = {
|
|||
} & EmbedProps;
|
||||
|
||||
export const getServerSideProps: GetServerSideProps<UserPageProps> = async (context) => {
|
||||
setCsrfToken(context.res);
|
||||
const ssr = await ssrInit(context);
|
||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req, context.params?.orgSlug);
|
||||
const usernameList = getUsernameList(context.query.user as string);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type { GetServerSidePropsContext } from "next";
|
||||
import { setCsrfToken } from "pages/api/auth/csrf";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Booker } from "@calcom/atoms";
|
||||
|
@ -103,7 +104,6 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) {
|
|||
} else if (bookingUid) {
|
||||
booking = await getBookingForSeatedEvent(`${bookingUid}`);
|
||||
}
|
||||
|
||||
// We use this to both prefetch the query on the server,
|
||||
// as well as to check if the event exist, so we c an show a 404 otherwise.
|
||||
const eventData = await ssr.viewer.public.event.fetch({
|
||||
|
@ -234,6 +234,7 @@ const paramsSchema = z.object({
|
|||
// Booker page fetches a tiny bit of data server side, to determine early
|
||||
// whether the page should show an away state or dynamic booking not allowed.
|
||||
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
||||
setCsrfToken(context.res);
|
||||
const { user } = paramsSchema.parse(context.params);
|
||||
const isDynamicGroup = user.length > 1;
|
||||
|
||||
|
|
|
@ -1,21 +1,26 @@
|
|||
import { serialize } from "cookie";
|
||||
import { randomBytes } from "crypto";
|
||||
import type { ServerResponse } from "http";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
export const setCsrfToken = (res: ServerResponse) => {
|
||||
const token = randomBytes(28).toString("hex");
|
||||
res.setHeader(
|
||||
"Set-Cookie",
|
||||
serialize("csrf_token", token, {
|
||||
httpOnly: false, // important for reading cookie on the client
|
||||
maxAge: undefined, // expire with session
|
||||
sameSite: "strict",
|
||||
path: "/",
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export default function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
console.log("✨ Getting CSRF token...");
|
||||
if (req.method === "GET") {
|
||||
const token = randomBytes(28).toString("hex");
|
||||
res.setHeader(
|
||||
"Set-Cookie",
|
||||
serialize("csrf_token", token, {
|
||||
httpOnly: false, // important for reading cookie on the client
|
||||
maxAge: undefined, // expire with session
|
||||
sameSite: "strict",
|
||||
path: "/",
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
})
|
||||
);
|
||||
setCsrfToken(res);
|
||||
res.status(200).json({ message: "OK!" });
|
||||
res.end();
|
||||
} else {
|
||||
|
|
|
@ -18,7 +18,7 @@ export async function ssrInit(context: GetServerSidePropsContext, options?: { no
|
|||
const ctx = await createContext(context);
|
||||
const locale = await getLocale(context.req);
|
||||
const i18n = await serverSideTranslations(locale, ["common", "vital"]);
|
||||
|
||||
ctx.req.headers["x-csrf-token"] = process.env.CSRF_SECRET;
|
||||
const ssr = createProxySSGHelpers({
|
||||
router: appRouter,
|
||||
transformer: superjson,
|
||||
|
|
|
@ -105,7 +105,8 @@
|
|||
"city-timezones": "^1.2.1",
|
||||
"eslint": "^8.34.0",
|
||||
"lucide-react": "^0.171.0",
|
||||
"turbo": "^1.10.1"
|
||||
"turbo": "^1.10.1",
|
||||
"universal-cookie": "^6.1.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"@apidevtools/json-schema-ref-parser": "9.0.9",
|
||||
|
|
|
@ -4,12 +4,16 @@ import { middleware } from "../trpc";
|
|||
|
||||
export const csrfMiddleware = middleware(({ ctx, next }) => {
|
||||
// Verify CSRF token
|
||||
const csrfCookie = ctx.req.cookies["csrf_token"];
|
||||
const csrfToken = ctx.req.headers["x-csrf-token"];
|
||||
const csrfCookie = ctx.req?.cookies["csrf_token"];
|
||||
const csrfToken = ctx.req?.headers["x-csrf-token"];
|
||||
console.table({
|
||||
"CSRF Token (from cookie)": csrfCookie,
|
||||
"CSRF Token (from headers)": csrfToken,
|
||||
});
|
||||
if (csrfToken && process.env.CSRF_SECRET && csrfToken === process.env.CSRF_SECRET) {
|
||||
console.info("CSRF secret detected, skipping middleware", process.env.CSRF_SECRET, csrfToken);
|
||||
return next();
|
||||
}
|
||||
if (!csrfToken || csrfToken !== csrfCookie) {
|
||||
throw new TRPCError({ code: "FORBIDDEN", message: "Invalid CSRF token" });
|
||||
}
|
||||
|
|
|
@ -330,6 +330,7 @@
|
|||
"ZOHOCRM_CLIENT_ID",
|
||||
"ZOHOCRM_CLIENT_SECRET",
|
||||
"ZOOM_CLIENT_ID",
|
||||
"ZOOM_CLIENT_SECRET"
|
||||
"ZOOM_CLIENT_SECRET",
|
||||
"CSRF_SECRET"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user