最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

express - CSRF Token won't be set unless the server sends a response. But CSRF token needed to make a request inside nux

programmeradmin1浏览0评论

Backend

  • Take this express backend server
const app = express();
app.use(rTracer.expressMiddleware());
app.use(requestLogger);
app.use(
  cors({
    credentials: true,
    origin: getAllowedOrigins,
  }),
);
app.use(
  helmet({
    contentSecurityPolicy: {
      directives: {
        frameAncestors: ["'self'", ''],
        defaultSrc: ["'self'"],
        scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'"],
        styleSrc: ["'self'", 'https:', "'unsafe-inline'"],
        baseUri: ["'self'"],
        fontSrc: ["'self'", 'https:', 'data:'],
        imgSrc: ["'self'", 'data:'],
      },
    },
    referrerPolicy: {
      policy: 'same-origin',
    },
  }),
);

app.set('trust proxy', 1);
app.use('/admin', adminRouter);
app.use(express.json({ limit: BODY_PARSER_LIMIT }));
app.use(express.urlencoded({ limit: BODY_PARSER_LIMIT, extended: false }));
app.use(sessionHandler);
app.use(passport.initialize());
app.use(passport.session());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/admin/queues', serverAdapter.getRouter());

const csrfProtection = new Tokens();

app.use((req: Request, res: Response, next: NextFunction) => {
  if (!req.cookies.csrfToken) {
    const token = csrfProtection.create('abracadabragilligillifoo');
    res.cookie('csrfToken', token, {
      httpOnly: false,
      maxAge: 86400000,
      sameSite: true,
      secure: false,
    });
  }
  next();
});


function verifyCsrfToken(req: Request, res: Response, next: NextFunction) {
  const csrfToken = req.cookies.csrfToken;
  const requestToken = req.headers['x-csrf-token'];

  // havent added verification yet
  // PRINTS undefined undefined on the first run since nuxtServerInit doesn't have the token
  console.log(csrfToken, requestToken, 'WWWWTTTTFFFF');
  next();
}

app.use('/', verifyCsrfToken, router);

Frontend

  • As you notice, unless someone actually hits an API endpoint inside router, a cookie will not be sent back containing the csrf token
  • But notice this nuxtServerInit endpoint where it makes all types of axios requests
export const actions = {
  async nuxtServerInit({ dispatch, rootGetters }, { error, req }) {
    try {
      console.log(req.headers.cookie);
      await dispatch('auth/fetchSession')
      await dispatch('news/popular/fetchNewsItems')
    } catch (err) {
      if (err.code === 'ECONNREFUSED') {
        error(
          'Servers are unreachable currently. If this issue persists, kindly open a support ticket here',
        )
      } else {
        error(err.message)
      }
    }
  },
}

  • The cookie with the value of csrfToken will be undefined before any endpoint is hit
  • But the endpoint requires a CSRF token to be present in order to actually work

Questions

  • How to beat this chicken/egg problem?
  • Is is actually safe to expose some GET /api/csrf endpoint?
  • What happens if the cookie is HTTP only?

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论