expressjs / csurf

CSRF token middleware
MIT License
2.3k stars 216 forks source link

Need docs and examples for working with single page application. #174

Closed mrdulin closed 5 years ago

mrdulin commented 5 years ago

For now, the docs give two examples. Both of them are based on server-side render.

The key point is: how to send csrf token to front-end domain.

back-end server will not render a <form> or index.html page so you can attach csrf-token to hidden form field or <meta> tag.

We also can't provide a api to grab the csrf-token.

back-end: http://localhost:3000 front-end: http://localhost:4200

I search a lot, but still do not find a solution for this case.

dougwilson commented 5 years ago

Thanks for the suggestion! I don't have any experience with what you mean, so no idea how to write docs on it. If you could contribute docs on this subject, it would certainly be welcome!

mrdulin commented 5 years ago

@dougwilson I got ForbiddenError: invalid csrf token on server-side.

This is my front-end request headers:

image

I set X-CSRF-Token header and withCredentials: true

Here is my server code:

function server() {
  const app = express();
  const PORT = 3000;

  const whitelist = ['http://localhost:4200'];
  app.use(
    cors({
      origin: whitelist,
      credentials: true
    })
  );
  app.use(cookieParser('cookie-secret'));
  app.use((req, res, next) => {
    console.log('cookies: ', req.cookies);
    console.log('req.headers: ', req.headers['x-csrf-token']);
    next();
  });
  app.use(csrf({ cookie: true }));

  app.get('/', (req, res) => {
    res.sendStatus(200);
  });

  app.get('/csrftoken', (req, res) => {
    const csrfToken = req.csrfToken();
    console.log('csrfToken: ', csrfToken);
    res.json({ csrfToken });
  });

  app.post('/api/user', (req, res) => {
    const user = { name: faker.name.findName(), email: faker.internet.email() };
    res.json(user);
  });

  return app.listen(PORT, () => {
    logger.info(`Server is listening on http://localhost:${PORT}`);
  });
}

Can you please take a look? thanks. Here are my code samples:

https://github.com/mrdulin/expressjs-research/tree/master/src/csrf/angular-sample-client https://github.com/mrdulin/expressjs-research/tree/master/src/csrf/angular-sample-server

Vasanthkesavan commented 5 years ago

I'm also dealing with something similar with angular as frontend. One tool which angular provides is HttpClientXSRF module.

Your imports should look like:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [
       BrowserModule, 
       HttpClientModule,
    **HttpClientXsrfModule.withOptions({
      cookieName: 'x-csrf-token',
      headerName: 'x-csrf-token'
    }),**
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}