0

Hello I want to add a middleware to implement a filter request in my frontend. Basically the workflow is the following: User login in page localhost:3000/auth Backend replies ok with access_token set in a cookie Front tries to redirect to /protected page because logged in. It triggers the middleware but when I try to access cookies I always get a empty object. I can see the cookies in my devtools. They are correctly set. But I cannot access them in the middleware. Why is that?

I created a middleware.ts file:

const protectedRoutes = ['/protected'];

export async function middleware(request: NextRequest) {
    const { cookies, nextUrl } = request;
    const test = request.cookies.get('access_token')
    console.log(request)
    if (!cookies) {
        return "prout"
    }
    const accessToken = cookies.get('access_token');

    const isProtected = protectedRoutes.includes(nextUrl.pathname);

    if (isProtected && !accessToken) {
        return NextResponse.redirect(new URL('/auth', request.url));
    }
    console.log(nextUrl.pathname)
    if (nextUrl.pathname === '/auth' && accessToken) {
        return NextResponse.redirect(new URL('/protected', request.url));
    }

    return NextResponse.next();
}

export const config = {
    matcher: ['/auth', '/protected'],
};

login method

    const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        setError("");
        try {
            const response = await loginUser(form);
            console.log(response)
            // setForm({ username: "", password: "" });
            router.push('/protected')
        } catch (error: any) {
            console.log(error)
            setError("Registration error: " + error.message);
        }
    };

backend login method:

async def login_user(db: AsyncSession, username: str, password: str):
    """
    check if correct credentials and return bearer token
    """
    user = await get_user_by_username(db, username)
    if not user or not verify_password(password, user.password):
        time.sleep(3)
        raise HTTPException(status_code=401, detail="Invalid credentials")
    access_token = create_access_token(
        {"sub": user.username}, 
        timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    )
    refresh_token = create_refresh_token(
        {"sub": user.username}, 
        expires_delta=timedelta(days=REFRESH_TOKEN_EXPIRE_DAYS)
    )
    csrf_token = generate_csrf_token()
    response = JSONResponse(content={"message": "Login successful"})

    response.set_cookie(
        key="access_token",
        value=access_token,
        httponly=True,
        path='/',
        samesite='none',
        secure=True
        )
    response.set_cookie(
        key="refresh_token",
        value=refresh_token,
        path='/', # TODO /refresh
        httponly=True,
        samesite='none',
        secure=True
    )
    response.set_cookie(
        key="csrf_token",
        value=csrf_token,
        httponly=False,
        path='/',
        samesite='none',
        secure=True
    )
    return response

2
  • httpOnly cookies are not accessible from the browser. Commented Apr 26 at 11:35
  • @HamedJimoh Thank you for your reply. So I presume middleware with httpOnly cookies is not possible. Is there another wya to do this? Commented Apr 26 at 13:27

1 Answer 1

1

The reason you're unable to access the cookie from your middleware even though the cookie is readily available in your browser cookie is because you have set the cookie as an httpOnly cookie. For security reasons, httpOnly cookies are typically only accessible in a server environment like NextJS Server Action or the API route handler. You cannot get hold of an httpOnly cookie in the middleware function using the request.cookies or the NextJS cookies() function.

If it becomes important for you to retrieve an httpOnly cookies inside the middleware function then you will have to manually retrieve the raw cookies from the request header. In your case, you can typically do something like this:

const protectedRoutes = ['/protected'];

export async function middleware(request: NextRequest) {
    let accessToken: string | undefined;
    const headerCookies = request.headers.get("cookie");
    if (headerCookies?.includes("access_token=")) {
    const tokenMatch = headerCookies.match(/access_token=([^;]+)/);
    accessToken = tokenMatch?.[1];
  }

    const isProtected = protectedRoutes.includes(nextUrl.pathname);

    if (isProtected && !accessToken) {
        return NextResponse.redirect(new URL('/auth', request.url));
    }
    console.log(nextUrl.pathname)
    if (nextUrl.pathname === '/auth' && accessToken) {
        return NextResponse.redirect(new URL('/protected', request.url));
    }

    return NextResponse.next();
}

export const config = {
    matcher: ['/auth', '/protected'],
};

You can still use the request.cookies.get() function to retrieve non-httpOnly cookies in your middleware function.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.