I cannot access cookies in middleware
Unanswered
Yellowfin tuna posted this in #help-forum
Yellowfin tunaOP
Good morning! I'm trying to implement protected routes using middleware in a Next.js 15 App Router project. I want to check for an access_token cookie to allow or block access to protected pages. However, I cannot read cookies via req.cookies.get("access_token").
Here is my middleware.js code (src/middleware.js)
import { NextResponse } from "next/server";
import { NextRequest } from "next/server";
const publicPaths = [
"/signin",
"/signup",
"/reset-password",
"/_next",
"/favicon.ico",
"/api",
];
export function middleware(req) {
const { pathname } = req.nextUrl;
if (publicPaths.some((path) => pathname.startsWith(path))) {
return NextResponse.next();
}
const token = req.cookies.get("access_token")?.value;
if (!token) {
return NextResponse.redirect(new URL("/signin", req.url));
}
return NextResponse.next();
}
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico|api).*)"],
};
The cookie is set on the server using cookies().set(...) from next/headers after successful login. Here’s an example of how it's being set:
Set-Cookie: access_token=...; Path=/; Expires=Tue, 13 May 2025 17:14:19 GMT; HttpOnly; Secure; SameSite=None
and refresh_token.
The issue:
Login is successful and cookies are set correctly (I can see both access_token and refresh_token in the browser under Application > Cookies).
But when I try to access a protected route, the cookie is not accessible in middleware.
Also, I’ve confirmed that the access_token and refresh_token are being sent in the request headers when I call a protected API endpoint — so cookies do exist.
What could be causing the middleware not to receive or see these cookies?
How can I fix this?
Here is my middleware.js code (src/middleware.js)
import { NextResponse } from "next/server";
import { NextRequest } from "next/server";
const publicPaths = [
"/signin",
"/signup",
"/reset-password",
"/_next",
"/favicon.ico",
"/api",
];
export function middleware(req) {
const { pathname } = req.nextUrl;
if (publicPaths.some((path) => pathname.startsWith(path))) {
return NextResponse.next();
}
const token = req.cookies.get("access_token")?.value;
if (!token) {
return NextResponse.redirect(new URL("/signin", req.url));
}
return NextResponse.next();
}
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico|api).*)"],
};
The cookie is set on the server using cookies().set(...) from next/headers after successful login. Here’s an example of how it's being set:
Set-Cookie: access_token=...; Path=/; Expires=Tue, 13 May 2025 17:14:19 GMT; HttpOnly; Secure; SameSite=None
and refresh_token.
The issue:
Login is successful and cookies are set correctly (I can see both access_token and refresh_token in the browser under Application > Cookies).
But when I try to access a protected route, the cookie is not accessible in middleware.
Also, I’ve confirmed that the access_token and refresh_token are being sent in the request headers when I call a protected API endpoint — so cookies do exist.
What could be causing the middleware not to receive or see these cookies?
How can I fix this?
13 Replies
Yellowfin tunaOP
Here is my login case:
Yellowfin tunaOP
Who can help me?
@chisto can you console.log(token) to see what's there
can you show application tab -> cookies ?
Yellowfin tunaOP
Sure, I tried to console.log(token) inside the middleware, but nothing appears in the logs. I think we cannot do logs in middleware.
are you checking the server logs? since middleware runs on the edge, the logs wont show on the browser, only on the server terminal
@chisto are you checking the server logs? since middleware runs on the edge, the logs wont show on the browser, only on the server terminal
Yellowfin tunaOP
Yes, I checked terminal, and unfortunately, there is no token
maybe its returning earlier? what happens if you comment the first if ?
@chisto maybe its returning earlier? what happens if you comment the first if ?
Yellowfin tunaOP
Finally but undefined)
try console.log(request.cookies); lets see whats there
or console.log(request.headers.get('cookie')); but you will get the big string and would have to split and stuff
@chisto or console.log(request.headers.get('cookie')); but you will get the big string and would have to split and stuff
Yellowfin tunaOP
I checked it in several ways
console.log("Request Cookies (direct):", req.cookies);
const cookieHeader = req.headers.get("cookie");
console.log("Cookie header:", cookieHeader);
const token = cookieHeader
?.split("; ")
.find((c) => c.startsWith("access_token="))
?.split("=")[1];
console.log("access_token:", token);
console.log("Request Cookies (direct):", req.cookies);
const cookieHeader = req.headers.get("cookie");
console.log("Cookie header:", cookieHeader);
const token = cookieHeader
?.split("; ")
.find((c) => c.startsWith("access_token="))
?.split("=")[1];
console.log("access_token:", token);
Snowshoe
I can see createAsyncThunk is redux function?
@Snowshoe I can see createAsyncThunk is redux function?
Yellowfin tunaOP
Of course, here is:
For login:
export const login = createAsyncThunk("auth/login", async (data, thunkAPI) => {
try {
const formattedPhone =
const response = await axios.post(
{
phonenumber: formattedPhone,
password: data.password,
},
{
withCredentials: true,
},
);
console.log("Full login response:", response);
console.log("Response headers:", response.headers);
console.log("Cookies in response:", document.cookie);
if (response.status === 200 response.status === 201) {
const user = response.data.data response.data.user response.data;
thunkAPI.dispatch(startRefreshInterval());
thunkAPI.dispatch(fetchUser());
return { user };
} else {
return thunkAPI.rejectWithValue({
message: "Unexpected response status",
});
}
} catch (error) {
return thunkAPI.rejectWithValue(error.response?.data error.message);
}
});
For getting the user data and also cookies:
export const fetchUser = createAsyncThunk(
"auth/fetchUser",
async (_, thunkAPI) => {
try {
const response = await axios.get(
withCredentials: true,
});
console.log("Fetched user", response.data);
return response.data;
} catch (error) {
if (error.response?.status === 401) {
await thunkAPI.dispatch(refreshToken());
const retryResponse = await axios.get(
withCredentials: true,
});
return retryResponse.data;
}
return thunkAPI.rejectWithValue(error.response?.data);
}
},
);
For login:
export const login = createAsyncThunk("auth/login", async (data, thunkAPI) => {
try {
const formattedPhone =
+998${data.phoneNumber.replace(/\D/g, "")}
;const response = await axios.post(
${API_BASE_URL}/auth/login
,{
phonenumber: formattedPhone,
password: data.password,
},
{
withCredentials: true,
},
);
console.log("Full login response:", response);
console.log("Response headers:", response.headers);
console.log("Cookies in response:", document.cookie);
if (response.status === 200 response.status === 201) {
const user = response.data.data response.data.user response.data;
thunkAPI.dispatch(startRefreshInterval());
thunkAPI.dispatch(fetchUser());
return { user };
} else {
return thunkAPI.rejectWithValue({
message: "Unexpected response status",
});
}
} catch (error) {
return thunkAPI.rejectWithValue(error.response?.data error.message);
}
});
For getting the user data and also cookies:
export const fetchUser = createAsyncThunk(
"auth/fetchUser",
async (_, thunkAPI) => {
try {
const response = await axios.get(
${API_BASE_URL}/auth
, {withCredentials: true,
});
console.log("Fetched user", response.data);
return response.data;
} catch (error) {
if (error.response?.status === 401) {
await thunkAPI.dispatch(refreshToken());
const retryResponse = await axios.get(
${API_BASE_URL}/auth
, {withCredentials: true,
});
return retryResponse.data;
}
return thunkAPI.rejectWithValue(error.response?.data);
}
},
);