Search code examples
reactjsflaskhttp-proxy-middlewareflask-jwt-extendedcookie-path

Flask-JWT-Extended: Ensure Refresh Cookie is Sent Only on `/refresh` but also on URLs with prefixes like `/api/refresh`


I am using Flask with the flask-jwt-extended library for authentication, and I have encountered an issue with the refresh cookie. My setup includes:

  • Backend: Flask running with flask run on port 5000.
  • Frontend: A React app running on port 3000, using a Node.js proxy (http-proxy-middleware).
  • Cookie Configuration:
    JWT_REFRESH_COOKIE_PATH = "/refresh"
    
    This ensures that the refresh cookie is sent only when making requests to /refresh. Cookie is set as httponly.

The Problem:

  • When I send a request directly to Flask (http://localhost:5000/refresh) (via Postman or Swagger documentation auto-generated by flask-restx), everything works fine.
  • When I send a request from the React app (http://localhost:3000/api/refresh), it is forwarded to Flask via the proxy. However, because the browser sees the request path as /api/refresh, it does not send the refresh cookie (since its Path is set to /refresh).

Node.js Proxy (setupProxy.js):

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

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

What I Want to Achieve:

I want the refresh cookie to be sent only for requests to /refresh, but I also need it to work:

  • When making a direct request to Flask (http://localhost:5000/refresh).
  • When making a request from the React app (http://localhost:3000/api/refresh), which is forwarded via the Node.js proxy to (http://localhost:5000/refresh).

What I Have Tried

  • dynamically setting the cookie path based on the request URL, but since the request always reaches Flask as /refresh, there’s no way to distinguish proxy requests.
  • changing JWT_REFRESH_COOKIE_PATH to "/api/refresh", but after it, only react app works and requests through auto-generated Swagger documentation don't work.
  • changing
module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://localhost:5000',
      changeOrigin: true,
    })
  );
};

to

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

but after this, even access to React app(http://localhost:3000) is redirected to http://localhost:5000

Question:

How can I configure flask-jwt-extended and/or http-proxy-middleware so that the refresh cookie is sent only on /refresh, while also allowing it to work correctly when requested from both direct backend access and through the React frontend proxy (/api/refresh)?

Any advice or suggestions would be greatly appreciated!


Solution

  • o3-mini suggested me to add cookiePathRewrite to setupProxy.js and it solved my problem:

    const {createProxyMiddleware} = require('http-proxy-middleware');
    module.exports = function (app) {
        app.use(
            '/api',
            createProxyMiddleware({
                target: 'http://localhost:5000',
                changeOrigin: true,
                cookiePathRewrite: {
                    '/refresh': '/api/refresh',
                },
            })
        );
    };