dotnet/aspnetcore · error · AntiforgeryValidationException

The required antiforgery header value "{0}" is not present.

Error message

The required antiforgery header value "{0}" is not present.

What it means

When HeaderName is configured and the request does not have form content (e.g. a JSON/API request), the request token must arrive via that header. If the header value is absent, AntiforgeryValidationException is thrown. This is the header-based validation path used by SPA/AJAX clients.

Source

Thrown at src/Antiforgery/src/Internal/DefaultAntiforgery.cs:162

        var tokens = await _tokenStore.GetRequestTokensAsync(httpContext);
        if (tokens.CookieToken == null)
        {
            throw new AntiforgeryValidationException(
                Resources.FormatAntiforgery_CookieToken_MustBeProvided(_options.Cookie.Name));
        }

        if (tokens.RequestToken == null)
        {
            if (_options.HeaderName == null)
            {
                var message = Resources.FormatAntiforgery_FormToken_MustBeProvided(_options.FormFieldName);
                throw new AntiforgeryValidationException(message);
            }
            else if (!httpContext.Request.HasFormContentType)
            {
                var message = Resources.FormatAntiforgery_HeaderToken_MustBeProvided(_options.HeaderName);
                throw new AntiforgeryValidationException(message);
            }
            else
            {
                var message = Resources.FormatAntiforgery_RequestToken_MustBeProvided(
                    _options.FormFieldName,
                    _options.HeaderName);
                throw new AntiforgeryValidationException(message);
            }
        }

        ValidateTokens(httpContext, tokens);

        _logger.ValidatedAntiforgeryToken();
    }

    private void ValidateTokens(HttpContext httpContext, AntiforgeryTokenSet antiforgeryTokenSet)
    {
        Debug.Assert(!string.IsNullOrEmpty(antiforgeryTokenSet.CookieToken));

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Read the antiforgery token from the cookie and send it in the configured header on AJAX requests.
  2. Confirm HeaderName matches between client and server configuration.
  3. Use the standard SPA pattern (fetch the token, set the XSRF header on mutating requests).

Example fix

// before
fetch('/api', { method: 'POST', body: JSON, headers: {} });

// after
fetch('/api', {
    method: 'POST',
    headers: { 'RequestVerificationToken': token },
    body: JSON
});
Defensive patterns

Strategy: try-catch

Validate before calling

// C# - confirm the configured header is present for non-form requests
if (_options.HeaderName != null
    && !httpContext.Request.HasFormContentType
    && !httpContext.Request.Headers.TryGetValue(_options.HeaderName, out var h)) {
    // client must resend the token in the header
}

Try / catch

// C#
try {
    await _antiforgery.ValidateRequestAsync(httpContext);
} catch (AntiforgeryValidationException ex) {
    // SPA/AJAX: instruct client to send RequestVerificationToken header
}

Prevention

When it happens

Trigger: HeaderName is set, the request is not form-encoded (JSON body), and the configured header (e.g. RequestVerificationToken) is missing or empty.

Common situations: SPA/AJAX/REST clients doing JSON POSTs without sending the antiforgery header; header name mismatch between client and server config; forgot to read the token from the cookie and resend it as a header.

Related errors


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/397ce3c0d5fdc471. Report an issue: GitHub.