Овов Очоы
Овов Очоы

Reputation: 513

Why are cookies not sent to the server via getServerSideProps in Next.js?

Cookies are not sent to the server via getServerSideProps, here is the code in the front-end:

export async function getServerSideProps() {
  const res = await axios.get("http://localhost:5000/api/auth", {withCredentials: true});
  const data = await res.data;
  return { props: { data } }
}

On the server I have a strategy that checks the access JWT token.

export class JwtStrategy extends PassportStrategy(Strategy, "jwt") {
    constructor() {
        super({
            ignoreExpiration: false,
            secretOrKey: "secret",
            jwtFromRequest: ExtractJwt.fromExtractors([
                (request: Request) => {
                    console.log(request.cookies) // [Object: null prototype] {}
                    let data = request.cookies['access'];
                    return data;
                }
            ]),
        });
    }

    async validate(payload: any){
        return payload;
    }
}

That is, when I send a request via getServerSideProps cookies do not come to the server, although if I send, for example via useEffect, then cookies come normally.

Upvotes: 23

Views: 28055

Answers (2)

Anurag Tripathi
Anurag Tripathi

Reputation: 1094

Explanation:

In Next.js, cookies are not automatically sent to the server via data fetching methods like getServerSideProps because these methods are executed on the server-side, and cookies are stored on the client-side. This means that if you're making a request from getServerSideProps, it will not have access to the client's cookies by default, and the request will be sent with an empty cookie.

Although, we can set the client's cookies in getServerSideProps by extracting them from the incoming request headers. Whenever a user requests a page from the browser, the request is sent to the frontend server where the Next.js application is running. The server then builds the initial HTML and executes getServerSideProps. At this point, Next.js inject context parameter to getServerSideProps that contains information about the incoming request, including the request object, response object, query parameters, and more. We can access the browser request headers and extract the cookies from there. Once we have the cookies, we can set them explicitly in any further request made from getServerSideProps.

export async function getServerSideProps(context) {
    const {req} = context;
    const res = await axios.get("http://localhost:5000/api/auth", {
        withCredentials: true,
        headers: {
            Cookie: req.headers.cookie //like this
        }
    });
    const data = await res.data;
    return { props: { data } }
}

Upvotes: 3

juliomalves
juliomalves

Reputation: 50358

That's because the request inside getServerSideProps doesn't run in the browser - where cookies are automatically sent on every request - but actually gets executed on the server, in a Node.js environment.

This means you need to explicitly pass the cookies to the axios request to send them through.

export async function getServerSideProps({ req }) {
    const res = await axios.get("http://localhost:5000/api/auth", {
        withCredentials: true,
        headers: {
            Cookie: req.headers.cookie
        }
    });
    const data = await res.data;
    return { props: { data } }
}

The same principle applies to requests made from API routes to external APIs, cookies need to be explicitly passed as well.

export default function handler(req, res) {
    const res = await axios.get("http://localhost:5000/api/auth", {
        withCredentials: true,
        headers: {
            Cookie: req.headers.cookie
        }
    });
    const data = await res.data;
    res.status(200).json(data)
}

Upvotes: 51

Related Questions