redux-toolkit: Cookies are not set with fetchBaseQuery

Hello,

I have tried setting cookies using RTK Query’s fetchBaseQuery with the option credentials: ‘include’, but it is not working. While doing the same request using fetch does work and sets the cookies like it should.

My server is running on: http://127.0.0.1:4000/api

I am using webpack, and I tried without any proxy and with these 2 proxies, but it won’t work in any case:

        proxy: {
            '/api':{
                changeOrigin: true,
                cookieDomainRewrite: 'localhost',
                target: 'http://localhost:4000',
                onProxyReq: (proxyReq) => {
                    if (proxyReq.getHeader('origin')) {
                      proxyReq.setHeader('origin', 'http://localhost:4000')
                    }
                }
            }
        }
     proxy: {
            '/api': {
               target: {
                  host: "127.0.0.1",
                  protocol: 'http:',
                  port: 4000
               },
               withCredentials: true,
            }
        },

This is authApi.tsx:

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { LoginValues } from '../../schema/login.interfaces';

export const authApi = createApi({
  reducerPath: 'authApi',
  baseQuery: fetchBaseQuery({
    baseUrl: "http://127.0.0.1:8080/api", // "http://127.0.0.1:4000/api" when using no proxy in webpack
    credentials: 'include', //Tried here
  }),
  endpoints: (builder) => ({
    login: builder.mutation<void, LoginValues>({
      query: (user) => ({
        url: '/auth/login',
        method: 'POST',
        body: user,
        // credentials: 'include', //And here
      }),
    }),
  }),
});

export const { useLoginMutation } = authApi;

Here is how I use it

export const LoginContainer: React.FC = () => {

  const [login, result] = useLoginMutation();

   const submit = async (data: LoginFormValues) => {
    // This calls the api and returns the right cookies in Set-Cookie header, but cookies are not set in the Application
    await login({
        email: 'hi@c.com',
         password: 'hellohello',
     });


    // But when I try it with a simple fetch like the following, it returns the right cookies and they are set in the Application
    // Tried with no proxy on webpack
    // const rawResponse = await fetch('http://localhost:4000/api/auth/login', {
    //   method: 'POST',
    //   headers: {
    //     Accept: 'application/json',
    //     'Content-Type': 'application/json',
    //   },
    //   body: JSON.stringify({
    //     email: 'hi@c.com',
    //     password: 'hellohello',
    //   }),
    //   credentials: 'include',
    // });

  };
  return (
    <>
      <Button onClick={submit}>Login</Button>
    </>
  );


}
export default LoginContainer;

Any idea how to set those cookies ?

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 2
  • Comments: 29 (7 by maintainers)

Most upvoted comments

I had this issue, and it took me several hours to resolve and these were my findings.

  1. This issue is not related to redux-toolkit or fetchBaseQuery,
  2. You need to add credentials:"include" in your base query for example
baseQuery: fetchBaseQuery({
    baseUrl: "api",
    credentials:"include"
  }),

and that’s all on the frontend side. 3. If you manage a server make sure you enable credentials and setup origin in your CORS configuration for example with express.

app.use(cors({
  credentials: true,
  origin: 'http://localhost:3000',
}));

Without setting them you’ll get CORS errors. 4. If you’re using cookieSession remember to set signed to false, secure to false while running locally

I had the same issue. Turned out that chrome was filtering out the cookies from the request because it was a “cross-site” request and the “secure”-flag on the Cookie was set to false.

So after setting sameSite: “None”, secure: true it’s now working.

I encountered this same issue after deploying my MERN app to render.com. The problem isn’t fetchBasedQuery but the cookies themselves. From this previous reply, When using cross-site cookies in chromium-based browsers, you have to set SameSite: "None" and Secure: true.

Also Remember to set the Access-Control-Allow-Credentials header to true, and if you’re using express js behind a reverse proxy, add app.set('trust proxy', 1); as well.

Hello! I had the same issue and i came with the solution just like so

1- on server side

app.use(cors(
    {
      origin: "http://localhost:3000/",
      credentials: true,
     }
));

res.cookie("jwt", token, {
    httpOnly: true,
    secure: true,
    sameSite: 'strict', // Enforce secure cookies & // Prevent CSRF attacks by setting sameSite
    maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
});

2- in client side

a- apiSlice.js

export const apiSlice = createApi({
      baseQuery: fetchBaseQuery({
      baseUrl: BASE_URL,
      prepareHeaders: (headers) => {
      return headers;
    },
  }),
    tagTypes: ["Products", "Orders", "Users"], 
    endpoints: (builder) => ({}),
});

b- usersApiSlice.js

export const usersApiSlice = apiSlice.injectEndpoints({
      endpoints: (builder) => ({
      registerUser: builder.mutation({
        query: (userData) => ({
        url: ${USER_URL}/register,
        method: "POST",
        body: userData,
      }),
     }),
    loginUser: builder.mutation({
       query: (userData) => ({
       url: ${USER_URL}/login,
       method: "POST",
       body: userData,
       credentials: "include",
     }),
    }),
    logoutUser: builder.mutation({
      query: () => ({ 
      url: ${USER_URL}/logout,
      method: "POST",
      credentials: "include",
     }),
   }),
 }),
}),

I hope that help 😊

I had the same issue. Turned out that chrome was filtering out the cookies from the request because it was a “cross-site” request and the “secure”-flag on the Cookie was set to false.

So after setting sameSite: “None”, secure: true it’s now working.

I tried doing same but it’s ignoring. Could you pls share how you did it. Btw I’m using fetch. Pls suggest

so what’s the solution to this? I’m facing the same problem req.cookies always return that ugly [Object: null prototype] {} …

If both your applications are on the localhost check that your baseUrl is “127.0.0.1” and not “localhost” (or vice versa I suppose). For me that was what was causing the queries to not include the cookie.

@arndvs @KLagdani I’m able to solve the issue, The only thing I did is the addition of a proxy to the application.

setupProxy.js

const { createProxyMiddleware } = require("http-proxy-middleware");

module.exports = function (app) {
  app.use(
    "/api",
    createProxyMiddleware({
      target: "http://localhost:5000",
      changeOrigin: true,
    })
  );
};



and change the baseQuery

  baseQuery: fetchBaseQuery({
    baseUrl: "api",
    headers: {
      "Content-Type": "application/json",
    },
    credentials:"include"
  }),

@phryneas ha yes indeed, the issue was located between the keyboard and the chair 😕

Depends if you want to send those cookies with every request. Usually I would assume you want that, so I’d add it to the baseQuery.