0

I'm using csurf to handle CSRF tokens in my express application, but I don't know where I'm supposed to create the token. I can't use the sign-in route, because the req.csrfToken() function is not available.

app.use(csrf({ cookie: true }))    
app.post('/signin', function (req, res) {
  // Authentication ...

  res.cookie('XSRF-TOKEN', req.csrfToken()); // Not possible (post request)
})

Should I create a new route for this that I use every time a user opens the front-end of my website?

app.use(csrf({ cookie: true }))    
app.get('/csrf', function (req, res) {
  res.cookie('XSRF-TOKEN', req.csrfToken());
})

Thanks in advance!

Edit: My frontend (react) is separate from the backend (express server)

SpoKaPh
  • 167
  • 2
  • 12

2 Answers2

0

There are several ways that you can set the CSRF Token:

  1. You can use it when rendering forms

JS:

var csrfProtection = csrf({ cookie: true })

app.get('/form', csrfProtection, function (req, res) {
  // pass the csrfToken to the view
  res.render('send', { csrfToken: req.csrfToken() })
});

HTML

 <input type="hidden" name="_csrf" value="{{csrfToken}}">
  1. You can use it as a cookie for all the routes. Recommended for Single Page Applications:
app.all('*', function (req, res) {
  res.cookie('XSRF-TOKEN', req.csrfToken())
  res.render('index')
})
  1. If you have a separate backend and frontend, you can use a middleware like below:

JS:

app.use(express.csrf());
app.use(function(req, res, next) {
  res.locals._csrf = req.csrfToken();
  next();
});

HTML:

input(type='hidden', name='_csrf', value=_csrf)

More info about this : http://sahatyalkabov.com/jsrecipes/#!/backend/csrf-protection-with-express

Harshana
  • 5,151
  • 1
  • 17
  • 27
  • I have a separate frontend (react) and backend (nodejs, express), so I don't use `res.render()` for my forms. I need some way to get the CSRF token from my express server to the frontend react application. – SpoKaPh Nov 16 '20 at 01:51
0

I ended up using the following code:

Express server:

app.use(cookieParser());
app.use(csrf({ cookie: true }));
app.get('/csrf', (req, res, next) => {
  res.send({'csrf_token':  req.csrfToken()});
});

App component in react:

useEffect(async () => {
  try {
    const res = await axios.get('http://api.myserver.com/csrf', { withCredentials: true });
    const csrfToken = (await axios.get('http://api.myserver.com/csrf')).data.csrf_token;
    // save csrfToken to redux store and include it in every request (-> axios interceptor)
  } catch (err) {
    //...
  }
}, [])
SpoKaPh
  • 167
  • 2
  • 12