Skip to content

feat: make CSRF cookie and header names configurable#3745

Open
yosofbadr wants to merge 3 commits intoplotly:devfrom
yosofbadr:feature/configurable-csrf-token
Open

feat: make CSRF cookie and header names configurable#3745
yosofbadr wants to merge 3 commits intoplotly:devfrom
yosofbadr:feature/configurable-csrf-token

Conversation

@yosofbadr
Copy link
Copy Markdown

@yosofbadr yosofbadr commented Apr 15, 2026

Summary

  • Add csrf_token_name and csrf_header_name config options to the Dash constructor
  • Allows users to match the CSRF cookie/header names used by their server framework (e.g. Django uses csrftoken instead of _csrf_token)
  • Values flow through Dash's standard config pipeline: Python app.config -> HTML _dash-config JSON -> frontend Redux store
  • getCSRFHeader() now reads cookie/header names from config with backward-compatible defaults
  • When the configured CSRF cookie is absent, no header is sent (previously sent undefined value)

Usage

# Django users
app = Dash(__name__, csrf_token_name="csrftoken")

# Custom CSRF setup
app = Dash(__name__, csrf_token_name="my_csrf", csrf_header_name="X-My-CSRF")

# Default behavior unchanged
app = Dash(__name__)  # uses '_csrf_token' / 'X-CSRFToken'

Motivation

Dash's frontend hardcodes the CSRF cookie name as _csrf_token, which conflicts with Django's default csrftoken. Users embedding Dash in Django apps with CSRF middleware enabled cannot use Dash without project-wide Django config changes. See #729 for full history.

This follows the architecture recommended by @chriddyp in #729: config variables should flow through Dash's standard config pipeline, not through hooks.

Prior art

PR #990 attempted this via the hooks system but was closed without review. This PR instead uses the config pipeline as maintainers requested.

Files changed

File Change
dash/dash.py Added params, config, validation, read-only, docstrings
dash-renderer/src/actions/index.js getCSRFHeader(config) with dynamic cookie/header names
dash-renderer/src/actions/api.js Pass config through GET/POST
dash-renderer/src/actions/callbacks.ts Pass config to getCSRFHeader
dash-renderer/src/config.ts Added optional fields to DashConfig type
tests/unit/test_configs.py 7 unit tests (defaults, custom, HTML output, validation, read-only)
CHANGELOG.md Added entry under UNRELEASED

Test plan

  • Unit tests for default config values
  • Unit tests for custom config values
  • Unit tests verifying config appears in generated HTML
  • Unit tests for input validation (empty/whitespace rejected)
  • Unit tests for read-only enforcement
  • Validated with Django 6.0 + CsrfViewMiddleware active
  • Renderer builds successfully
  • ESLint + Prettier pass on all JS/TS changes
  • Black + flake8 pass on all Python changes
  • CI integration tests

Fixes #729

Add `csrf_token_name` and `csrf_header_name` config options to the Dash
constructor, allowing users to match the CSRF cookie/header names used
by their server framework (e.g. Django uses 'csrftoken').

The values flow through Dash's standard config pipeline: Python
`app.config` -> HTML `_dash-config` JSON -> frontend Redux store.
`getCSRFHeader()` now reads these from config with backward-compatible
defaults ('_csrf_token' / 'X-CSRFToken'). When the configured cookie
is absent, no CSRF header is sent (previously sent undefined value).

Fixes plotly#729
@yosofbadr yosofbadr marked this pull request as draft April 15, 2026 19:17
@yosofbadr yosofbadr marked this pull request as ready for review April 16, 2026 04:39
@yosofbadr
Copy link
Copy Markdown
Author

Regarding the 2 remaining Percy visual diffs:

  1. Error dialog — same content, slightly different scroll position (no functional change)
  2. Dropdown search — appears to show a different filter state at the time of Percy snapshot capture. The dcc.Dropdown filtering is client-side React code, which this PR does not modify. Our changes are limited to how CSRF headers are attached to HTTP requests.

All integration and unit tests pass. These appear to be Percy snapshot timing differences, not functional regressions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Name of CSRF cookie is hard-coded.

1 participant