Next.js Discord

Discord Forum

app.use() alternative in Next Js

Answered
Parson Russell Terrier posted this in #help-forum
Open in Discord
Parson Russell TerrierOP
hello everyone i want to use app.use(helmet()) middleware in my next js so how can i use it?? please help
Answered by joulev
you can't use helmet()* in nextjs, but to return http headers, you can use the headers() option in next.config.js https://nextjs.org/docs/app/api-reference/next-config-js/headers, or set the headers in middleware https://nextjs.org/docs/app/building-your-application/routing/middleware#setting-headers

* unless you are willing to follow the custom server route https://nextjs.org/docs/pages/building-your-application/configuring/custom-server, in that case adding helmet directly is possible
View full answer

16 Replies

@Parson Russell Terrier hello everyone i want to use app.use(helmet()) middleware in my next js so how can i use it?? please help
you can't use helmet()* in nextjs, but to return http headers, you can use the headers() option in next.config.js https://nextjs.org/docs/app/api-reference/next-config-js/headers, or set the headers in middleware https://nextjs.org/docs/app/building-your-application/routing/middleware#setting-headers

* unless you are willing to follow the custom server route https://nextjs.org/docs/pages/building-your-application/configuring/custom-server, in that case adding helmet directly is possible
Answer
helmet uses the res.setHeader syntax, which is not how middleware sets response header. it's probably silently failing
@joulev really? how did you do it?
Parson Russell TerrierOP
import { NextRequest, NextResponse } from "next/server";
import { jwtVerify } from "jose";
import { UserJWTPayload } from "./shared/types/JWT";
//@ts-ignore
import xssClean from "xss-clean";
import expressMongoSanitize from "express-mongo-sanitize";

export const getJwtSecretKey = () => {
  const secret = process.env.JWT_SECRET_KEY;
  if (!secret || secret.length === 0) {
    throw new Error("env JWT_SECRET_KEY is not set.");
  }
  return secret;
};

const verifyJWTToken = async (token: string) => {
  try {
    const verified = await jwtVerify(
      token,
      new TextEncoder().encode(getJwtSecretKey())
    );
    return verified.payload as UserJWTPayload;
  } catch (err) {
    throw new Error("Your token has expired! please sign in");
  }
};

export async function middleware(req: NextRequest) {
  if (req.nextUrl.pathname.startsWith("/api")) {
    xssClean();
    expressMongoSanitize();
  } else {
    const token = req.cookies.get("token")?.value;
    const verifyToken =
      token &&
      (await verifyJWTToken(token).catch((err) => {
        console.log(err);
      }));
    // if user is not authenticared than allow him to got to login & register page
    if (
      (req.nextUrl.pathname.startsWith("/login") ||
        req.nextUrl.pathname.startsWith("/register")) &&
      !verifyToken
    ) {
      return;
    }
    const url = req.url;
    //   if user is authenticated and he tries to navigate to /login and /register than redirect to home page
    if ((url.includes("/login") || url.includes("/register")) && verifyToken) {
      return NextResponse.redirect(new URL("/", url));
    }
    if (!verifyToken) {
      return NextResponse.redirect(new URL("/login", url));
    }
  }
}

export const config = {
  matcher: ["/", "/login", "/register", "/api/:path*"],
};
@Parson Russell Terrier tsx import { NextRequest, NextResponse } from "next/server"; import { jwtVerify } from "jose"; import { UserJWTPayload } from "./shared/types/JWT"; //@ts-ignore import xssClean from "xss-clean"; import expressMongoSanitize from "express-mongo-sanitize"; export const getJwtSecretKey = () => { const secret = process.env.JWT_SECRET_KEY; if (!secret || secret.length === 0) { throw new Error("env JWT_SECRET_KEY is not set."); } return secret; }; const verifyJWTToken = async (token: string) => { try { const verified = await jwtVerify( token, new TextEncoder().encode(getJwtSecretKey()) ); return verified.payload as UserJWTPayload; } catch (err) { throw new Error("Your token has expired! please sign in"); } }; export async function middleware(req: NextRequest) { if (req.nextUrl.pathname.startsWith("/api")) { xssClean(); expressMongoSanitize(); } else { const token = req.cookies.get("token")?.value; const verifyToken = token && (await verifyJWTToken(token).catch((err) => { console.log(err); })); // if user is not authenticared than allow him to got to login & register page if ( (req.nextUrl.pathname.startsWith("/login") || req.nextUrl.pathname.startsWith("/register")) && !verifyToken ) { return; } const url = req.url; // if user is authenticated and he tries to navigate to /login and /register than redirect to home page if ((url.includes("/login") || url.includes("/register")) && verifyToken) { return NextResponse.redirect(new URL("/", url)); } if (!verifyToken) { return NextResponse.redirect(new URL("/login", url)); } } } export const config = { matcher: ["/", "/login", "/register", "/api/:path*"], };
yes, here xssClean() and expressMongoSanitize() do nothing
@joulev yes, here xssClean() and expressMongoSanitize() do nothing
Parson Russell TerrierOP
🥲 why?
nextjs follows a different syntax from express, things using express syntax does not work in nextjs
Parson Russell TerrierOP
okay i thought this will work as this is similar to app.use
so how can i configure these 2 packages in my code correctly??
@Parson Russell Terrier okay i thought this will work as this is similar to app.use so how can i configure these 2 packages in my code correctly??
for xss-clean and express-mongo-sanitize: you have to sanitise and validate user input manually in the api routes. can't do it in middleware.

about helmet(): build and send the http headers manually https://nextjs.org/docs/app/building-your-application/routing/middleware#setting-headers
@Parson Russell Terrier okay understood, so in my case what will happen in those 2 lines??
nothing.

xssClean() (and similar functions) returns a function (req, res, next) => { ... }. these functions only work in places where (req, res, next) => {...} is expected, e.g. inside express .use().

in your case, these functions are simply declared and left as is. it is like this

function generateAdder() {
  return function (a, b) {
    return a + b;
  };
}

function main() {
  generateAdder();
}

the a + b part is never run, so the function does nothing.
Parson Russell TerrierOP
is this correct way to sanitize the fields?? @joulev