Skip to content

fix(auth): Fix CSRF token refresh for multi-tab auth scenarios#107214

Merged
JoshFerge merged 2 commits intomasterfrom
jferg/csrf-token-refresh-fix
Jan 30, 2026
Merged

fix(auth): Fix CSRF token refresh for multi-tab auth scenarios#107214
JoshFerge merged 2 commits intomasterfrom
jferg/csrf-token-refresh-fix

Conversation

@JoshFerge
Copy link
Member

@JoshFerge JoshFerge commented Jan 29, 2026

Summary

  • Moves the CSRF token cross-tab synchronization from organization-login.html to the base auth.html template
  • Synchronization logic now uses csrfEls.length > 0 and loops through ALL CSRF elements instead of only one.

Problem

Users experience "CSRF token from POST incorrect" errors when:

  1. They have multiple tabs open on auth pages
  2. One tab completes login (rotating the CSRF token)
  3. Other tabs try to submit with stale CSRF tokens

The original cross-tab synchronization was introduced in #32592, but it only worked when there was exactly 1 CSRF form (SSO auth orgs). This PR also fixes it to work on orgs without SSO, where there are multiple login forms (login + register) with multiple tokens.

Solution

Move the cross-tab synchronization to the base auth.html template so ALL auth pages benefit:

  • login.html
  • twofactor.html
  • twofactor_u2f.html
  • organization-login.html
  • oauth-authorize.html
  • oauth-device.html
  • And other auth templates

Test plan

  1. Open two tabs to /auth/login/sentry/
  2. In browser console on both tabs, check CSRF values: document.getElementsByName('csrfmiddlewaretoken')[0].value
  3. Log in on Tab 1
  4. Check Tab 2 - the CSRF values should update within 200ms
  5. Submitting on Tab 2 should succeed (no CSRF error)

Known limitation

WebAuthn/passkey auto-submit (form.submit()) may still race ahead of the 200ms interval. This is a narrower edge case. If we still observe problems, we can likely lower the interval.

Monitoring:

we can use this logs query to observe if the number of users hitting this error decreases after the change.

Can monitor as we rollout to confirm changes don't degrade auth, during my local testing all looks good.

Users experience "CSRF token from POST incorrect" errors when:
1. They have multiple tabs open on auth pages
2. One tab completes login (rotating the CSRF token)
3. Other tabs try to submit with stale CSRF tokens

The existing CSRF refresh hack in organization-login.html was broken:
`csrfEls.length == 1` fails when there are 2+ forms (login + register).

This change:
- Moves the CSRF refresh hack to the base auth.html template so ALL
  auth pages benefit (login, 2fa, oauth, etc.)
- Fixes the bug by using `csrfEls.length > 0` and looping through
  all CSRF elements instead of just updating the first one
- Removes the broken duplicate code from organization-login.html
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Jan 29, 2026
@JoshFerge JoshFerge marked this pull request as ready for review January 29, 2026 01:20

{% load crispy_forms_tags %}
{% load i18n %}
{% load sentry_assets %}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this just load our tags library so it adds nonce on the javascript we're adding, most of the relevant pages this inherits from already load it anyways.

Copy link
Contributor

@cathteng cathteng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think is this fine but I asked Cursor if there were other HTML forms that this doesn't cover and moving the logic to modal.html would cover all forms (e.g. organization-auth-provider-settings.html)

@JoshFerge
Copy link
Member Author

I think is this fine but I asked Cursor if there were other HTML forms that this doesn't cover and moving the logic to modal.html would cover all forms (e.g. organization-auth-provider-settings.html)

do you know if this problem happens for non-login forms as well?

@JoshFerge JoshFerge merged commit 97593dc into master Jan 30, 2026
63 checks passed
@JoshFerge JoshFerge deleted the jferg/csrf-token-refresh-fix branch January 30, 2026 20:11
priscilawebdev pushed a commit that referenced this pull request Feb 2, 2026
## Summary
- Moves the CSRF token cross-tab synchronization from
`organization-login.html` to the base `auth.html` template
- Synchronization logic now uses `csrfEls.length > 0` and loops through
ALL CSRF elements instead of only one.

## Problem
Users experience "CSRF token from POST incorrect" errors when:
1. They have multiple tabs open on auth pages
2. One tab completes login (rotating the CSRF token)
3. Other tabs try to submit with stale CSRF tokens

The original cross-tab synchronization was introduced in
#32592, but it only worked when
there was exactly 1 CSRF form (SSO auth orgs). This PR also fixes it to
work on orgs without SSO, where there are multiple login forms (login +
register) with multiple tokens.

## Solution
Move the cross-tab synchronization to the base `auth.html` template so
ALL auth pages benefit:
- `login.html`
- `twofactor.html`
- `twofactor_u2f.html`
- `organization-login.html`
- `oauth-authorize.html`
- `oauth-device.html`
- And other auth templates

## Test plan
1. Open two tabs to `/auth/login/sentry/`
2. In browser console on both tabs, check CSRF values:
`document.getElementsByName('csrfmiddlewaretoken')[0].value`
3. Log in on Tab 1
4. Check Tab 2 - the CSRF values should update within 200ms
5. Submitting on Tab 2 should succeed (no CSRF error)

## Known limitation
WebAuthn/passkey auto-submit (`form.submit()`) may still race ahead of
the 200ms interval. This is a narrower edge case. If we still observe
problems, we can likely lower the interval.


## Monitoring:
we can use this
[logs](https://console.cloud.google.com/logs/query;query=resource.type%3D%22k8s_container%22%0Alabels.name%3D%22sentry.web.frontend.csrf_failure%22%0AjsonPayload.reason%3D%22CSRF%20token%20from%20POST%20incorrect.%22;summaryFields=:true:32:beginning;cursorTimestamp=2026-01-29T01:08:45.304939119Z;duration=P30D?project=internal-sentry)
query to observe if the number of users hitting this error decreases
after the change.

Can monitor as we rollout to confirm changes don't degrade auth, during
my local testing all looks good.
@github-actions github-actions bot locked and limited conversation to collaborators Feb 15, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants