dotnet/aspnetcore · critical · InvalidOperationException

The antiforgery system has the configuration value {optionNa

Error message

The antiforgery system has the configuration value {optionName} = {value}, but the current request is not an SSL request.

What it means

Thrown by CheckSSLConfig (DefaultAntiforgery.cs:252-259) when AntiforgeryOptions.Cookie.SecurePolicy is set to CookieSecurePolicy.Always but the current request is not HTTPS. This is a fail-fast guard: the secure cookie policy is meaningless over plain HTTP, so the system throws InvalidOperationException rather than silently emitting an insecure cookie. CheckSSLConfig is called at the start of every public antiforgery method (GetAndStoreTokens, GetTokens, IsRequestValidAsync, ValidateRequestAsync, SetCookieTokenAndHeader).

Source

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

        {
            // Persist the new cookie if it is not null.
            _tokenStore.SaveCookieToken(httpContext, cookieToken);
        }

        if (!_options.SuppressXFrameOptionsHeader && !httpContext.Response.Headers.ContainsKey(HeaderNames.XFrameOptions))
        {
            // Adding X-Frame-Options header to prevent ClickJacking. See
            // http://tools.ietf.org/html/draft-ietf-websec-x-frame-options-10
            // for more information.
            httpContext.Response.Headers.XFrameOptions = "SAMEORIGIN";
        }
    }

    private void CheckSSLConfig(HttpContext context)
    {
        if (_options.Cookie.SecurePolicy == CookieSecurePolicy.Always && !context.Request.IsHttps)
        {
            throw new InvalidOperationException(Resources.FormatAntiforgery_RequiresSSL(
                string.Join(".", nameof(AntiforgeryOptions), nameof(AntiforgeryOptions.Cookie), nameof(CookieBuilder.SecurePolicy)),
                nameof(CookieSecurePolicy.Always)));
        }
    }

    private static IAntiforgeryFeature GetAntiforgeryFeature(HttpContext httpContext)
    {
        var antiforgeryFeature = httpContext.Features.Get<IAntiforgeryFeature>();
        if (antiforgeryFeature is null)
        {
            antiforgeryFeature = new AntiforgeryFeature();
            httpContext.Features.Set(antiforgeryFeature);
        }

        return antiforgeryFeature;
    }

    private IAntiforgeryFeature GetCookieTokens(HttpContext httpContext)

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Ensure the app receives HTTPS: call app.UseHttpsRedirection() or use HTTPS in development (dotnet run with launchSettings https profile).
  2. If behind a reverse proxy that terminates TLS, configure UseForwardedHeaders so IsHttps reflects the original scheme via X-Forwarded-Proto.
  3. If HTTPS isn't possible, set Cookie.SecurePolicy to None or SameAsRequest instead of Always — though this reduces security.
  4. For local dev, use the HTTPS URL (https://localhost:5001) rather than http://localhost:5000.

Example fix

// before — SecurePolicy Always but no HTTPS in dev
builder.Services.AddAntiforgery(o =>
    o.Cookie.SecurePolicy = CookieSecurePolicy.Always);

// after — honor forwarded headers behind TLS-terminating proxy
builder.Services.Configure<ForwardedHeadersOptions>(o =>
    o.ForwardedHeaders = ForwardedHeaders.XForwardedProto);
app.UseForwardedHeaders();
Defensive patterns

Strategy: validation

Validate before calling

// Check before calling antiforgery APIs
if (_antiforgeryOptions.Cookie.SecurePolicy == CookieSecurePolicy.Always
    && !httpContext.Request.IsHttps)
{
    // redirect to HTTPS or adjust SecurePolicy
    return Redirect("https://" + httpContext.Request.Host + httpContext.Request.Path);
}

Try / catch

try
{
    await _antiforgery.ValidateRequestAsync(httpContext);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("SSL"))
{
    _logger.LogCritical("Antiforgery requires HTTPS but request is HTTP");
    return BadRequest("HTTPS is required.");
}

Prevention

When it happens

Trigger: Any call to IAntiforgery while Cookie.SecurePolicy == Always and httpContext.Request.IsHttps == false. This includes local development over http://localhost, or a production deployment behind a reverse proxy that terminates TLS and forwards plain HTTP to the app.

Common situations: Local development without HTTPS; reverse proxy (Nginx/HAProxy/Azure App Gateway) terminating TLS and not forwarding the X-Forwarded-Proto header; UseHttpsRedirection missing from the pipeline; a misconfigured forward headers setup.

Understand the failure class

Related errors


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