How to set a custom cookie with auth middleware and retain behavior? #11692
-
This is for 5.x: If I have the following middleware definition, it works great: export { auth as middleware } from "@/auth";
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}; I now want to add a custom cookie in this middleware: import { auth } from "@/auth";
import { ORG_ID_COOKIE_NAME } from "@/config/constants.common";
import { serverEnvs } from "@/config/constants.server";
import { createClient } from "@hey-api/client-fetch";
import { getDefaultOrganizationId } from "@internal/portal-client";
import { NextResponse } from "next/server";
export default auth(async (request) => {
const response = NextResponse.next({
request,
});
if (!request.cookies.has(ORG_ID_COOKIE_NAME) && request?.auth?.token) {
const apiClient = createClient({
baseUrl: serverEnvs.PUBLIC_BACKEND_URL,
headers: {
Authorization: `Bearer ${request.auth.token.accessToken}`,
},
});
const result = await getDefaultOrganizationId({ client: apiClient });
response.cookies.set({
name: ORG_ID_COOKIE_NAME,
value: result.data.organizationId,
secure: true,
sameSite: "strict",
});
}
return response;
});
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}; However, when I do this, it no longer properly gates (as in redirects to login) if don't have session cookies. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
I figured it out. This is because in the https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/lib/index.ts#L261 } else if (userMiddlewareOrRoute) {
// Execute user's middleware/handler with the augmented request
const augmentedReq = request as NextAuthRequest
augmentedReq.auth = auth
response =
(await userMiddlewareOrRoute(augmentedReq, args[1])) ??
NextResponse.next() and a branch for a not authorized situation with no custom middleware: https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/lib/index.ts#L268 } else if (!authorized) {
const signInPage = config.pages?.signIn ?? `${config.basePath}/signin`
if (request.nextUrl.pathname !== signInPage) {
// Redirect to signin page by default if not authorized
const signInUrl = request.nextUrl.clone()
signInUrl.pathname = signInPage
signInUrl.searchParams.set("callbackUrl", request.nextUrl.href)
response = NextResponse.redirect(signInUrl)
}
} and as a result, when using custom middleware, you'll have to handle the unauthorized situation yourself. What I did was I exported the import { auth, authConfig } from "@/auth";
import { ORG_ID_COOKIE_NAME } from "@/config/constants.common";
import { serverEnvs } from "@/config/constants.server";
import { createClient } from "@hey-api/client-fetch";
import { getDefaultOrganizationId } from "@internal/portal-client";
import { NextResponse } from "next/server";
export default auth(async (request) => {
if (!request.auth?.token?.accessToken) {
// Replicates https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/lib/index.ts#L268
// This is the default behavior if custom middleware isn't defined and we don't have authorization
const signInPage = authConfig.pages?.signIn ?? `${authConfig.basePath}/signin`;
if (request.nextUrl.pathname !== signInPage) {
// Redirect to signin page by default if not authorized
const signInUrl = request.nextUrl.clone();
signInUrl.pathname = signInPage;
signInUrl.searchParams.set("callbackUrl", request.nextUrl.href);
return NextResponse.redirect(signInUrl);
}
}
const response = NextResponse.next({
request,
});
if (!request.cookies.has(ORG_ID_COOKIE_NAME) && request?.auth?.token?.accessToken) {
const apiClient = createClient({
baseUrl: serverEnvs.PUBLIC_BACKEND_URL,
headers: {
Authorization: `Bearer ${request.auth.token.accessToken}`,
},
});
const result = await getDefaultOrganizationId({ client: apiClient });
response.cookies.set({
name: ORG_ID_COOKIE_NAME,
value: result.data.organizationId,
secure: true,
sameSite: "strict",
});
}
return response;
});
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}; |
Beta Was this translation helpful? Give feedback.
-
A suggestion for improving this:
|
Beta Was this translation helpful? Give feedback.
I figured it out. This is because in the
nextAuth
function, there's a branch specifically for custom middleware:https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/lib/index.ts#L261
and a branch for a not authorized situation with no custom middleware:
https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/lib/index.ts#L268