Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

node.js - ForbiddenError: invalid csrf token (NodeJS, Express)

First time adding SCRF protection by 'csurf' module. I want to put SCRF-token into cookie, pull it on client side and make a SCRF-token header that will be compared with SCRF-token from cookies on server side caused by every POST/PUT requests. My stack is: React + Redux + NodeJS + Express. But I'm always getting ForbiddenError: invalid csrf token. Its seems so minor, but I already wasted one day for fixing it. I'm definately missing smth evident(((
Server:

app.js

import { CookieOptions } from './types/server';
import express, { Request, Response, Express } from "express";
import path from 'path'
import https from 'https';
import fs from 'fs';
import csrf from 'csurf';
import helmet from 'helmet';
import cors from "cors";
import cookieSession from "cookie-session";
import passport from "passport";
import 'dotenv/config';
import logger, { morganOption } from "./config/winston";
import morgan from "morgan";
import routes from './routes/index'
import cookieParser from 'cookie-parser';
import bodyParser from 'body-parser';

const app: Express = express();
const port: string | number = process.env.PORT || 3000;

const httpsOptions = {
  key: fs.readFileSync("./config/www/keys/key.pem"),
  cert: fs.readFileSync("./config/www/keys/cert.pem")
};

const cookieOptions: CookieOptions = {
  maxAge: 30 * 24 * 60 * 60 * 1000,
  keys: [process.env.COOKIE_KEY],
  resave: false,
  saveUninitialized: false,
  secure: true,
  httpOnly: true
}

app.use(morgan("combined", morganOption));
app.use(cors());
app.use(helmet());
app.use(express.json());
app.use(cookieParser())
app.use(cookieSession(cookieOptions));
app.use(passport.initialize());
app.use(csrf({ cookie: { key: 'XSRF-TOKEN' } }));
app.use('/', routes);

const mode: string = process.env.NODE_ENV;

try {
  if (mode === "production ") {
    app.use(express.static("../client/build"));
    app.get("*", (req: Request, res: Response) => {
      res.sendFile(path.resolve(__dirname, "/index.html"));
    });
  }
  https.createServer(httpsOptions, app).listen(port, () => {
    console.log("Server works on port: " + port);
  });
} catch (error) {
  console.log("Error: " + error);
  process.exit(1);
}

export default app

User:

input.js:

import React from "react";
import classes from "./input.module.scss";
import { Props } from "../../../types/components/input";

const Input: React.FC<Props> = (props) => {
  const inputClasses = props.error
    ? `${classes.input} ${classes.invalid}`
    : classes.input;
  const spanClasses = props.error
    ? `${classes.input__inform} ${classes.invalid}`
    : classes.input__inform;

  return (
    <div className={classes.wrapper}>
      <input type="hidden" name="XSRF-TOKEN" value=""/>
      <input
        className={inputClasses}
        defaultValue={props.value}
        type={props.type}
        autoComplete={props.autoComplete}
        name={props.name}
        placeholder={props.placeholder}
        ref={props.register(props.rules)}
        onChange={(evt) => props.onChangeHandler(evt.target.value, props.name)}
      />
      <span className={spanClasses}>
        {props.error ? props.error.message : props.inform}
      </span>
    </div>
  );
};

export default Input;

Its creating a header:

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: ru-UA,ru;q=0.9,uk-UA;q=0.8,uk;q=0.7,en-US;q=0.6,en;q=0.5,ru-RU;q=0.4
Connection: keep-alive
Content-Length: 52
Content-Type: application/json;charset=UTF-8
Cookie: XSRF-TOKEN=KL6lJ5ycmqwJgAsop78o5zhN
Host: localhost:3006
Origin: https://localhost:3006
Referer: https://localhost:3006/signin
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36
X-XSRF-TOKEN: KL6lJ5ycmqwJgAsop78o5zhN

But middleware always throws an error((
If compare it manually, I'm getting true:

app.use('/', (req, res, next) => {
  console.log(req.headers.cookie.match(/(?<=XSRF-TOKEN=).+/g)[0] === req.headers['x-xsrf-token'])
  next();
});
question from:https://stackoverflow.com/questions/65938894/forbiddenerror-invalid-csrf-token-nodejs-express

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...