dotnet/aspnetcore · error · InvalidOperationException

The antiforgery system has the configuration value

Error message

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

What it means

Thrown in CheckSSLConfig when the antiforgery cookie is configured with CookieSecurePolicy.Always but the current request is not HTTPS. The cookie policy demands an encrypted channel, so the validator refuses to operate over plain HTTP. It is an InvalidOperationException indicating a deployment/configuration mismatch.

Solutions

  1. Use HTTPS for the endpoint that performs antiforgery (set ASPNETCORE_URLS=https://, bind a dev cert, or terminate TLS at the edge correctly).
  2. If HTTPS is terminated upstream, enable ForwardedHeaders middleware so IsHttps reflects the original scheme.
  3. If plain HTTP is genuinely required in a trusted context, set Cookie.SecurePolicy to SameAsRequest or None (not recommended for production).
  4. For local dev, launch the app with the https:// profile (dotnet run --launch-profile https) so IsHttps is true.

Example fix

// before: HTTPS terminated at proxy but not forwarded
app.UseAntiforgery(); // throws over http

// after: forward upstream TLS info
app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedProto });
Defensive patterns

Strategy: validation

Validate before calling

if (antiforgeryOptions.Cookie.SecurePolicy == CookieSecurePolicy.Always && !httpContext.Request.IsHttps) { /* reject/redirect to https before validation */ }

Try / catch

try { CheckSSLConfig(httpContext); }
catch (InvalidOperationException) { httpContext.Response.Redirect(httpsUrl); return; }

Prevention

When it happens

Trigger: AntiforgeryOptions.Cookie.SecurePolicy == CookieSecurePolicy.Always and a request arrives where context.Request.IsHttps is false (http:// URL, or HTTPS terminated upstream and not forwarded with the right headers).

Common situations: Running locally over http://localhost with SecurePolicy.Always; HTTPS terminated at a load balancer/reverse proxy without ForwardedHeaders configured so IsHttps reads false; cookie policy set globally to Always but a health/internal endpoint exposed over HTTP.

Understand the failure class

Related errors


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

Appendix: 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 3600ca084e)