Replies: 1 comment
-
I was able to get this working with a hacky middleware for all /api routes. Here's what it looks like with a Nextjs middleware.ts file in the root: // middleware.ts
import { HEADER_CSRF } from "@blitzjs/auth";
import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
const AntiCSRFBodySchema = z.object({
[HEADER_CSRF]: z.string().min(1),
});
// Handle request body with form data encoding
const getAntiCSRFFromFormData = async (req: NextRequest): Promise<string | undefined> => {
try {
const body = await req.formData();
if (body.has(HEADER_CSRF)) {
const token = (body.get(HEADER_CSRF) || "").toString();
if (token.length > 0) return token;
}
} catch (err) {
// Fail silently
}
return undefined;
};
// Handle request body with JSON data encoding
const getAntiCSRFFromJSONData = async (req: NextRequest): Promise<string | undefined> => {
try {
const body = await req.json();
const parsedBody = AntiCSRFBodySchema.safeParse(body);
if (parsedBody.success) {
return parsedBody.data[HEADER_CSRF];
}
} catch (err) {
// Fail silently
}
return undefined;
};
export const middleware = async (req: NextRequest, resp: NextResponse) => {
const { pathname } = req.nextUrl;
// Set the anti-csrf header from the body to all /api routes if present
if (pathname.startsWith("/api")) {
const [formCSRF, jsonCSRF] = await Promise.all([
getAntiCSRFFromFormData(req),
getAntiCSRFFromJSONData(req),
]);
const token = formCSRF || jsonCSRF;
if (token == null) return NextResponse.next();
// First, clone the existing headers
let requestHeaders = new Headers(req.headers);
try {
if (requestHeaders.has(HEADER_CSRF)) {
// Update to match form/body data if it already exists
requestHeaders.set(HEADER_CSRF, token);
} else {
// Otherwise add it
requestHeaders.append(HEADER_CSRF, token);
}
// Return the response with the updated request headers
return NextResponse.next({
request: {
headers: requestHeaders,
},
});
} catch (err) {
// Fail silently
}
}
return NextResponse.next();
};
export const config = {
matcher: ["/api/:path*"],
}; I'll try to refactor this into a Blitz middleware if I have time. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I see the docs for including the
anti-csrf
token header but I want to have a form submit to an api endpoint so I can send a file to the browser with the response.Here's an example of the form I would want:
Here's an example of the api handlers to send the file:
Is it possible to include an
anti-csrf
hidden input?Otherwise, if there is a way to disable the anti-csrf check for an api endpoint can you share that? If nothing else I could disable the header check and then check for the field in the form data and validate it myself.
Beta Was this translation helpful? Give feedback.
All reactions