The error I get:
Error: Cannot read properties of null (reading ‘name’)
<h1 className="text-4xl font-bold">Welcome {user.name}!</h1>
Expected result:
- Delete access token
- Regenerate the access token with the refresh token
- const user populate
What seems to be happening:
- Delete access token
- const user populate
- Regenerate the access token with the refresh token
In short words, the variable is getting populated before the token is re-generated.
Infact if you refresh the page it gets populated.
How can I fix it?
I’m using Next.js 14.2.4
import {getUser} from "@/utils/user";
const Admin = () => {
const user = getUser() ;
return (
<section className="container">
<h1 className="text-4xl font-bold">Welcome {user.name}!</h1>
</section>
);
};
export default Admin;
user.ts
import { cookies } from "next/headers";
import { jwtDecode } from "jwt-decode";
interface User {
userId: number;
name: string;
email: string;
iat: number;
exp: number;
}
export function getUser(): User | null {
const token = cookies().get("accessToken")?.value;
if (token) {
try {
return jwtDecode(token);
} catch (error) {
console.error("Failed to decode token:", error);
return null;
}
}
return null;
}
Middleware
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { SignJWT, jwtVerify, type JWTPayload } from "jose";
async function refreshAccessToken(refreshToken: string) {
const isRefreshTokenValid = await jwtVerify(refreshToken, new TextEncoder().encode(process.env.JWT_REFRESH_SECRET));
if (isRefreshTokenValid) {
const { id, name, email } = isRefreshTokenValid.payload;
const payload = { id, name, email };
const jwt = await new SignJWT(payload)
.setProtectedHeader({ alg: "HS256" })
.setIssuedAt()
.setExpirationTime("15m")
.sign(new TextEncoder().encode(process.env.JWT_SECRET));
const response = NextResponse.next();
response.cookies.set({
name: "accessToken",
value: jwt,
maxAge: 60 * 15,
});
return response;
}
return NextResponse.redirect("http://localhost:3000/login");
}
export async function middleware(request: NextRequest) {
const accessToken = request.cookies.get("accessToken")?.value;
const refreshToken = request.cookies.get("refreshToken")?.value;
if (accessToken) {
const isAccessTokenValid = await jwtVerify(accessToken, new TextEncoder().encode(process.env.JWT_SECRET));
return isAccessTokenValid ? NextResponse.next() : NextResponse.redirect("http://localhost:3000/login");
}
if (refreshToken) {
return refreshAccessToken(refreshToken);
}
return NextResponse.redirect("http://localhost:3000/login");
}
export const config = {
matcher: "/admin/",
};