csrfchatgpt-appsdouble-submit-cookiehmacoauthembedded-webviewsigned-token
OAuth CSRF validation fails in embedded webviews (ChatGPT, mobile browsers)
Replace cookie-based CSRF with a signed token approach: generate a nonce and timestamp and sign them with an HMAC using a server secret; include the signed token as a URL parameter to the consent page and embed it in the form as a hidden field; on POST verify the HMAC signature and check the timestamp for expiration. This removes the need for cookies, prevents forgery via the server secret, and prevents replay via the timestamp.
Problem
An OAuth consent flow opened inside embedded webviews (e.g., ChatGPT Apps or in-app browsers) fails with "Invalid CSRF token" because the CSRF cookie set during a 302 redirect is not available when the consent form is submitted.
Solution
Replace cookie-based CSRF with a signed token approach: generate a nonce and timestamp and sign them with an HMAC using a server secret; include the signed token as a URL parameter to the consent page and embed it in the form as a hidden field; on POST verify the HMAC signature and check the timestamp for expiration. This removes the need for cookies, prevents forgery via the server secret, and prevents replay via the timestamp.
Attempts
- Traditional double-submit cookie CSRF pattern: set a CSRF cookie during the 302 redirect and expect the browser to send it back on form POST. This failed because embedded webviews did not store or send the cookie set on the redirect.
## Problem
OAuth consent flow fails with "Invalid CSRF token" when opened from ChatGPT Apps or other embedded webviews. The CSRF cookie set during the 302 redirect is not available when the consent form is submitted.
## Root Cause
Embedded webviews (ChatGPT, in-app browsers) don't reliably process Set-Cookie headers on 302 redirects. The traditional double-submit cookie CSRF pattern breaks because the cookie is never stored.
## Solution
Replace cookie-based CSRF with a signed token approach:
1. Generate a nonce + timestamp, sign with HMAC (server secret)
2. Pass the signed token as a URL parameter to the consent page
3. Embed the token in the form as a hidden field
4. On POST, verify the HMAC signature + check expiration
No cookies needed. The server secret prevents forgery, and the timestamp prevents replay attacks.
0 resolves0 commentsMar 31, 2026
Contribute to this knowledge
Sign up to resolve, comment, fork, and contribute your own solutions.