Skip to content

Cross-Site RequestForgery (CSRF) Protection

The IOTO web server provides comprehensive protection against Cross-Site Request Forgery (CSRF) attacks. CSRF attacks trick a user's browser into sending unauthorized commands to a web server by leveraging an active user session.

To mitigate this, the web server employs CSRF tokens. This document outlines how to configure and use this protection mechanism.

Mitigation Strategy

The CSRF protection is based on a double-submit cookie pattern using a cryptographically strong token.

  1. A unique CSRF token is generated on the server for a user session.
  2. The token is sent to the client as a X-XSRF-TOKEN response header with the first GET request. The client must save this token.
  3. For subsequent state-changing requests (POST, PUT, DELETE), the client must include the token in the request, either in the X-XSRF-TOKEN header or as a form parameter.
  4. The server validates the received token against the one stored in the user's session. If they do not match, the request is rejected with a 400 Bad Request status.

This ensures that only requests originating from pages served by your web server can perform sensitive actions.

Configuration

CSRF protection is configured in the web.json5 file. Note that in the configuration and source code, XSRF is used as an abbreviation for CSRF.

To enable CSRF protection for a specific route, add the xsrf: true property to its definition in the routes array.

To ensure client-side scripts can access the CSRF token, the X-XSRF-TOKEN header must be exposed. Add 'Access-Control-Expose-Headers': 'X-XSRF-TOKEN' to the headers section.

json5
{
    routes: [
        { match: '/api/resource/', handler: 'action', xsrf: true },
        // ... other routes
    ],
    headers: {
        'Access-Control-Expose-Headers': 'X-XSRF-TOKEN',
    },
}

When CSRF protection is enabled for a route, a session is automatically created to store the token on the server. The session ID is returned to the client in a secure, HttpOnly session cookie with SameSite=Lax.

Token Naming

You can customize the token names if required:

  • Default header name: X-XSRF-TOKEN
  • Default form parameter name: -xsrf-

Client-Side Workflow

  1. Enable CSRF protection in the web.json5 configuration for the required routes.
  2. Request a Token: Make an initial GET request to a protected route.
  3. Extract and Store: From the response, extract the value of the X-XSRF-TOKEN header and store it securely on the client-side.
  4. Submit the Token: For any subsequent POST, PUT, or DELETE request, include the stored token in one of two ways:
    • As an X-XSRF-TOKEN request header.
    • As a hidden form input with the name -xsrf-.

Implementation Details

  • CSRF tokens are only created for routes that have xsrf: true enabled.
  • For GET requests to a protected route, the webAddSecurityToken() function is automatically called to generate and add the CSRF token to the response headers.
  • For incoming POST, PUT, or DELETE requests, webCheckSecurityToken() is called to validate the token.
  • If the token is missing or invalid, the request is rejected.