ASP.NET Core
Add Centinel Analytica to your ASP.NET Core application.
Overview
The Centinel middleware runs before your endpoints, sending request metadata to the validator API. The validator decides if the request should be allowed, blocked, redirected, or didn't match any protected path. Blocked and challenged responses are rendered from HTML the validator returns, so that traffic never reaches your endpoints. Two cases do fall through to your app: a challenge that arrives without HTML, and a misconfigured CentinelConfiguration section.
Prerequisites
- .NET 9.0 SDK or later (the package targets
net9.0) - NuGet package access
- Centinel secret key (from the Dashboard)
Install
In your ASP.NET Core project:
dotnet add package Centinel.AspNetCoreConfigure
Add your Centinel settings to appsettings.json (or any other configuration provider):
{
"CentinelConfiguration": {
"SecretKey": "YOUR_SECRET_KEY",
"ValidatorApiUrl": "https://validator.centinelanalytica.com/validate",
"ProtectedPaths": ["/api", "/dashboard"],
"ExcludedPaths": ["/health", "/static"],
"FailOpen": true
}
}| Property | Type | Required | Default | Description |
|---|---|---|---|---|
SecretKey | string | Yes | – | Secret key for the validator API. |
ValidatorApiUrl | string | No | https://validator.centinelanalytica.com/validate | Validator endpoint URL. |
ProtectedPaths | string[] | No | – | Routes to validate. If empty, all routes are protected. |
ExcludedPaths | string[] | No | – | Routes to skip validation on. |
FailOpen | boolean | No | true | If false, return 503 with Service temporarily unavailable when the Centinel API is unreachable. |
RequestTimeout | TimeSpan | No | 00:00:05 | Validator request timeout. |
EnableLogging | boolean | No | true | Emit validator request and response logs. |
CookieName | string | No | _centinel | Session cookie the middleware reads. |
ProtectedPaths and ExcludedPaths are case-insensitive prefix matches with no wildcards, and
exclusions always win. A prefix of /api therefore also matches /apiary, so add a trailing
slash (/api/) when you mean a path segment.
Register Centinel in Program.cs:
using Centinel.AspNetCore.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCentinel(builder.Configuration);
// Or configure manually:
// builder.Services.AddCentinel(options =>
// {
// options.SecretKey = Environment.GetEnvironmentVariable("CENTINEL_SECRET_KEY")!;
// options.ProtectedPaths = new() { "/api", "/admin" };
// });
var app = builder.Build();Put the Centinel middleware in your request pipeline before endpoint execution:
using Centinel.AspNetCore.Extensions;
app.UseCentinel();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();Put UseCentinel() first. The middleware reads context.Request.Path directly and needs no routing
data, so placing it ahead of routing and auth keeps unwanted traffic away from that work entirely.
Confirm the config actually bound
If the CentinelConfiguration section is missing or misspelled, the middleware allows every request and logs Centinel configuration is invalid. Requests will be allowed through. The check runs per request, not at startup, so send a request first and then read the logs. Nothing appears in your startup output either way, and under production traffic this line repeats on every request.
The NuGet package does not inject the browser script. Add the script tag
to _Layout.cshtml yourself if you want browser-side signals.
Middleware
With app.UseCentinel(), every matching request is validated automatically. Use ProtectedPaths and ExcludedPaths in your configuration to control which routes get checked.
Inject ICentinelValidator to apply Centinel only where you need it (e.g. sensitive APIs) without middleware-wide protection.
Custom validator endpoint
Override the validator URL or request timeout if you're using a self-hosted validator:
builder.Services.AddCentinel(options =>
{
options.SecretKey = Environment.GetEnvironmentVariable("CENTINEL_SECRET_KEY")!;
options.ValidatorApiUrl = "https://validator.yourdomain.com/validate";
options.RequestTimeout = TimeSpan.FromSeconds(10);
});Deployment notes
Make sure your production configuration or environment variables include the CentinelConfiguration values (especially SecretKey and any custom validator URL). Restart your app after updating keys so the middleware picks up the new settings.
Verify
With EnableLogging on and the log level at Debug, curl an excluded path and then a protected one.
A protected request logs Sending validation request to Centinel API for URL: {Url} followed by
Received validation response: {Decision}.
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:5000/health
curl -s -o /dev/null -w '%{http_code}\n' -A 'python-requests/2.31' http://localhost:5000/api/itemsFour log lines tell you what went wrong when it doesn't work:
| Log line | Meaning |
|---|---|
Centinel configuration is invalid | The config section did not bind. Everything is allowed. |
Centinel API returned status {StatusCode} | Usually a wrong secret key. |
Centinel API request timed out for URL | Raise RequestTimeout, or check egress. |
Centinel API unavailable, allowing request through | Fail-open engaged. |
The repo ships a runnable demo under demo/ with public and protected routes if you want to see all
of this without touching your own app.
Changelog
- v1.0.1 — Response header passthrough