GithubHelp home page GithubHelp logo

Comments (9)

LoicPoullain avatar LoicPoullain commented on May 22, 2024 1

Hi @Jrfidellis ,

It is an interesting question.

Before going further on whether a CSRF token is necessary or not, I’ll dwell a bit on some definitions and concepts of web development.

General Concepts

1. Cookies

Cookies are a just a technology to:

  • store small pieces of data on the client host (using a key/value mechanism),
  • and send and set this data to and from the server.

For example, if we want to save the value xfe4h8ame56ez with the name my_key on the client host, the server can add the header Set-Cookie: my_key=xfe4h8ame56ez; Path=/ in its HTTP response. When receiving it, the user’s web browser creates a cookie called my_key with the value xfe4h8ame56ez. Then, on every new request to the server, the browser sends back the value of this cookie by adding the header Cookies: my_key=xfe4h8ame56ez in the request.

As a result, cookies do not define whether a communication is stateless or not. It’s just a technology to store small pieces of data (user preferences, themes, session id, api key, etc). But they are generally very useful (and largely used) when working with stateful sessions.

2. Stateless communication

In the original thesis that introduces the REST architectural style, Roy Thomas Fielding defines the client-stateless-server style as follows:

Each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client.

In a stateless communication, servers do not have stored contexts.

A word about sessions (to understand the definition): a session describes the fact that we keep a state across several requests. They are usually divided in three categories :

  • Client sessions store the state on the client host.
  • Server sessions store the state on the server in memory (default behavior of the express-session middleware) or in a file.
  • Database sessions store the state in an database. Django and FoalTS store by default the state in the SQL database. In general, database sessions are stored in a redis database.

Usually when people talk about sessions they mean server or database sessions.

3. Stateless or stateful?

Using stateless communication is indubitably easier. As we don’t have to manage stored contexts on the servers, the scalability and the deployments are facilitated.

However, in many situations (logging, csrf protections, etc), we cannot get rid of stateless communication. That’s why, as a convention, we usually speak of RESTful APIs when the communication is really stateless.

What about CSRF protections?

Coming soon!

from foal.

LoicPoullain avatar LoicPoullain commented on May 22, 2024

Hi @Jrfidellis ,

Sorry for the late reply!

FoalTS aims to eventually be a backend framework for Single Page Applications. The reason why the "get started" tutorial uses Server Side Rendering is for simplicity. The beginner does not have to know a particular frontend framework to learn FoalTS and he/she usually understands what SSR does.

However future releases will focus on how to integrate FoalTS with a frontend application. Especially the createapp command will support three special flags --angular, --vue and --react to directly use FoalTS with these three common frameworks. Basically here are the steps that the command will follow :

  • Install the CLI of the frontend framework if it hasn't been already installed.
  • Create the frontend app with this CLI.
  • Create the backend app with the FoalTS CLI.
  • Create and update files to link both projects and make them work both together in development and production (for example: setting a proxy in development to redirect requests from the Angular port 4200 to port 3000).

I will first focus on the Angular integration and the docs will then have a "Get started with Angular" tutorial.

Regarding the LoginController, the generated controller indeed uses the SRR pattern with redirections. But you can also avoid these redirections by removing the redirect property. If you feel like updating the authentication doc, I'll review it ;)

redirect = {
  // if `logout` is not defined then the server returns a 204 when requesting GET /logout.
  // if `success`  is not defined then the server returns a 204 on success.
  // if `failure`  is not defined then the server returns a 401 on failure.
};

A last word about SSR: even if we eventually use a SPA in the frontend we will need to use SSR when the application loads to send the csrf token.

from foal.

Jrfidellis avatar Jrfidellis commented on May 22, 2024

Thank you, that makes sense.

I just have one more question:

A last word about SSR: even if we eventually use a SPA in the frontend we will need to use SSR when the application loads to send the csrf token.

Why a CSRF token is even necessary whit REST? I believe that a REST API should be stateless and should not accept data from either a browser cookie or session (directly). Limiting the request source (to the frontend URL, for example) should be enough to prevent CSRF. (using SSR CSRF seems necessary, no doubt).

I'm using this conversation as a opportunity to learn so don't mind if i say nonsense, if you could help me understand i would be grateful.

When i get some extra time i will submit a PR with the doc changes.

Thanks @LoicPoullain!

from foal.

LoicPoullain avatar LoicPoullain commented on May 22, 2024

Hi @Jrfidellis, just a little message to tell you that I have not forgotten your question. I just want to meet someone next week (working in security) to discuss about this, to be sure of my answer;).

from foal.

Jrfidellis avatar Jrfidellis commented on May 22, 2024

Thank you very much @LoicPoullain! I'm looking forward to know about your thoughts on CSRF.

There is just one thing that i disagree there.. in my opinion a ideal API shoudn't send a header like Set-cookie, the API should send back the token (xfe4h8ame56ez) in the request body and the frontend should decide what to do with him.

I suppose that send a header like Set-cookie wouldn't work if you are calling the API from a mobile app or desktop application.

"As a result, cookies do not define whether a communication is stateless or not." Agreed, i was wrong about that.

from foal.

LoicPoullain avatar LoicPoullain commented on May 22, 2024

There is just one thing that i disagree there.. in my opinion a ideal API shoudn't send a header like Set-cookie, the API should send back the token (xfe4h8ame56ez) in the request body and the frontend should decide what to do with him.

I guess that it depends on the context. I saw some people saving their JWT in a cookie and some other not. One advantage of saving a token in a cookie with the option HttpOnly: true is that the token cannot be stolen via an XSS attack. However, that's right, it's more common to see the key/token sent back in the request body (or custom header).

I suppose that send a header like Set-cookie wouldn't work if you are calling the API from a mobile app or desktop application.

I think some libraries must exist to parse cookie headers on mobile or desktop apps since they are just strings with keys / values. I didn't do a lot of mobile programming though to confirm it.

What about CSRF tokens ?

Applications using authentication with sessions/cookies are more vulnerable to CSRF attacks. A malicious website A may send a request to B to perform a certain action. And as B's cookies will be (theoretically) sent with it, the B server will receive the authentication token and so allows the action.

One way to prevent that is to ask for a CSRF token. This token is sent in every page of B and required in any incoming request. This way, requests made from A to B won't work, since A does not have the CSRF token.

Drawbacks of using CSRF tokens

Using CSRF tokens can be annoying as it requires SSR, which is not convenient when developing a SPA with Angular/Vue/React, and sessions, making it more difficult to manage scalability and frequent deployments.

I guess this is your point (tell me if I'm wrong). I might have found a solution in the next comment to solve this problem. Let me know what you think.

Note: Even when using authentication with JWT, you will need, at some point, to store a context on the server to support token blacklisting. This context may be stored in a file (server session) or in a database (database session).

Same origin

Over the last years, some new protections have come up to mitigate the risk of CSRF attacks.

Limiting the request source (to the frontend URL, for example) should be enough to prevent CSRF

Recent browsers prevents cross-origin requests. The Same-origin policy checks that both URLs have the same origin (same port, same protocol, same host). This a client-side protection and so depends on whether the user keeps their browser up-to-date.

capture d ecran 2019-01-21 a 09 56 39

Note: a lot of tutorials around the web disables this protection by using the cors middleware to connect frontend and backend during development.

Limiting the request source can also be done in the server side and it is one of the defense-in-depth mitigation techniques presented by OWASP. However, OWASP still recommends to use a token based mitigation with it as primary defense (see here)

Interesting resources

OWASP: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Warning:_No_Cross-Site_Scripting_.28XSS.29_Vulnerabilities

OWASP: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)

html5rocks: https://www.html5rocks.com/en/tutorials/cors/

from foal.

LoicPoullain avatar LoicPoullain commented on May 22, 2024

During the docs examples and getting started we can see that the MVC architectural pattern is used, it's also used in the generated codes (ex: the CLI's generate controller, choosing Login. The controller handles the redirects and also the rendering of the login page).

I would like to know why MVC was chosed as the main architectural pattern (if it was) and if you think it is interesting to create a Web API option (maybe during foal createapp).

I don't know if the terminology in my question is right, but with MVC i mean Server Side Rendering of the Pages.

When reading your first post and some other comments I've received since, I feel that most people want to create a REST API with a front end (SPA) and handle authentication with JWT and localStorage. Was it / is it your case?

If so, I was thinking about disabling the CSRF protection by default in every new project and replace the SSR example with a simple ApiController. This would remove some "noise" and make the "getting started" easier.

Currently

config/settings.json

{
  "csrf": true
}

Directory structure:

src/
  app/
    controllers/
      view.controller.ts
    app.controller.ts

app.controller.ts

import { controller } from '@foal/core';

import { ViewController } from './controllers';

export class AppController {
  subControllers = [
    controller('/', ViewController),
  ];
}

controllers/view.controller.ts

import { Config, Get, render } from '@foal/core';

export class ViewController {

  @Get('/')
  index(ctx) {
    return render('./templates/index.html', {
      appName: Config.get('app', 'name'),
      csrfToken: ctx.request.csrfToken(),
    }, __dirname);
  }

}

After

config/settings.json

{
  "csrf": false
}

Directory structure:

src/
  app/
    controllers/
      api.controller.ts
    app.controller.ts

app.controller.ts

import { controller } from '@foal/core';

import { ApiController } from './controllers';

export class AppController {
  subControllers = [
    controller('/api', ApiController),
  ];
}

controllers/api.controller.ts

import { Config, Get, HttpResponseOK } from '@foal/core';

export class ApiController {

  @Get('/')
  index(ctx) {
    return new HttpResponseOK('Hello world!');
  }

}

What do you think? Would it be better that way?

from foal.

Jrfidellis avatar Jrfidellis commented on May 22, 2024

Hi Loïc,

I feel that most people want to create a REST API with a front end (SPA) and handle authentication with JWT and localStorage. Was it / is it your case?

Yes, it is my case.

What do you think? Would it be better that way?

It would be better that way because it is the way that (i think) most part of the developers will be interested in using Foal.

from foal.

LoicPoullain avatar LoicPoullain commented on May 22, 2024

The PR has been merged #315 . Closing this issue

from foal.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.