Claude
Skills
Sign in
Back

identity-security-hardening

Included with Lifetime
$97 forever

Security hardening for Duende IdentityServer deployments including signing key rotation, HTTPS enforcement, CORS configuration, CSP headers, rate limiting, token lifetime tuning, and security audit patterns.

Security

What this skill does


# Identity Security Hardening

## When to Use This Skill

Use this skill when:
- Hardening a Duende IdentityServer deployment before promoting to production
- Configuring HTTPS, HSTS, and TLS requirements for the identity server host
- Evaluating or enforcing client secret policies (shared secrets vs. certificates vs. `private_key_jwt`)
- Setting PKCE requirements, restricting grant types, or locking down redirect URI validation
- Configuring Content Security Policy (CSP) and CORS for IdentityServer UI pages and endpoints
- Applying rate limiting to the token endpoint to protect against brute-force and enumeration attacks
- Tuning token lifetimes, enabling reference tokens, or implementing token replay detection
- Rotating signing keys or choosing between RS256 and ES256 algorithms
- Hardening session lifetimes, idle timeouts, and back-channel logout behavior
- Auditing an existing IdentityServer setup against OAuth 2.0 Security Best Current Practice (RFC 9700)

## Core Principles

1. **HTTPS Everywhere** — IdentityServer must only be reachable over HTTPS in production. Any HTTP request should be permanently redirected. HSTS with `includeSubDomains` and `preload` is the minimum bar.
2. **Reduce Token Blast Radius** — Short access token lifetimes, reference tokens for sensitive APIs, and audience validation ensure that a stolen token can do minimal damage.
3. **PKCE is Non-Negotiable** — Every authorization code flow client must use PKCE, regardless of whether it is a public or confidential client. `RequirePkce = true` is the default; never disable it.
4. **Asymmetric Client Authentication** — Prefer certificate-based or `private_key_jwt` client authentication over shared secrets. Secrets that are never transmitted cannot be stolen in transit.
5. **Strict Redirect URI Matching** — Wildcards in redirect URIs are a critical attack surface. Every production URI must be fully qualified and must match exactly.
6. **Restrict Grant Types Per Client** — Every client should only allow the grant types it actually uses. Disabling implicit flow and unused grants is one of the highest-impact, lowest-effort hardening steps.
7. **Defense in Depth** — Combine transport security, token constraints, rate limiting, CSP, and CORS into a layered defense. No single control is sufficient.

## Related Skills

- `identityserver-configuration` — Server-side configuration of clients, resources, and signing keys that these hardening patterns build upon
- `oauth-oidc-protocols` — Protocol-level context for PKCE, PAR, DPoP, and grant type trade-offs
- `aspnetcore-authentication` — Applying OIDC authentication hardening in client applications
- `aspnetcore-authorization` — Enforcing authorization policies that consume the hardened tokens produced here

Docs: https://docs.duendesoftware.com/identityserver/configuration/security

---

## Sub-Documents

| Document | Description | When to Load |
|----------|-------------|--------------|
| [docs/cors-csp.md](docs/cors-csp.md) | CORS `ICorsPolicyService` implementation and CSP middleware with header examples | CORS origins, Content-Security-Policy, X-Frame-Options, clickjacking, custom CORS policy |
| [docs/rate-limiting.md](docs/rate-limiting.md) | ASP.NET Core `AddRateLimiter` configuration for token and authorization endpoints | Rate limiting, brute force, 429, sliding window, fixed window, token endpoint protection |
| [docs/session-hardening.md](docs/session-hardening.md) | Server-side sessions, cookie lifetime configuration, back-channel logout client setup | Session security, CookieSlidingExpiration, BackChannelLogoutUri, session fixation, inactivity |

---

## Pattern 1: Transport Security — HTTPS, HSTS, and TLS

IdentityServer handles credentials and tokens. Every byte must travel over TLS. ASP.NET Core provides the pipeline middleware to enforce this.

```csharp
// ✅ Program.cs — production pipeline ordering
var app = builder.Build();

// 1. HTTPS redirection — permanent redirect (308) for any HTTP request
app.UseHttpsRedirection();

// 2. HSTS — tell browsers to always use HTTPS for this host
// includeSubDomains: all subdomains also require HTTPS
// preload: opt-in to browser preload lists (requires max-age >= 1 year)
app.UseHsts();

app.UseIdentityServer();
app.UseAuthorization();
```

Configure HSTS options in `Program.cs` before `Build()`:

```csharp
// ✅ Strong HSTS configuration
builder.Services.AddHsts(options =>
{
    options.MaxAge = TimeSpan.FromDays(365);
    options.IncludeSubDomains = true;
    options.Preload = true;

    // Optionally exclude development/staging hosts
    // options.ExcludedHosts.Add("localhost");
});

// ✅ Force HTTPS redirect to use 443 explicitly
builder.Services.AddHttpsRedirection(options =>
{
    options.RedirectStatusCode = StatusCodes.Status308PermanentRedirect;
    options.HttpsPort = 443;
});
```

### Behind a Reverse Proxy

When IdentityServer sits behind a load balancer or reverse proxy that terminates TLS, the inner request arrives as HTTP. Configure `ForwardedHeaders` so IdentityServer sees the correct scheme:

```csharp
// ✅ Required when hosted behind a load balancer or ingress
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders =
        ForwardedHeaders.XForwardedFor |
        ForwardedHeaders.XForwardedProto;

    // Restrict to known proxy IPs — never accept from any source
    options.KnownProxies.Add(IPAddress.Parse("10.0.0.1"));
    options.ForwardLimit = 1;
});

// Must be the very first middleware in the pipeline
app.UseForwardedHeaders();
app.UseHttpsRedirection();
app.UseHsts();
app.UseIdentityServer();
```

> **Important:** Without `ForwardedHeaders`, IdentityServer publishes an `http://` issuer URI in the discovery document, causing token validation failures in every downstream API.

### Kestrel TLS Configuration

For direct Kestrel hosting (no reverse proxy), configure TLS explicitly:

```csharp
// ✅ Kestrel TLS — require TLS 1.2 minimum
builder.WebHost.ConfigureKestrel(options =>
{
    options.ConfigureHttpsDefaults(https =>
    {
        https.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13;
        https.ClientCertificateMode = ClientCertificateMode.NoCertificate;
    });
});
```

---

## Pattern 2: Signing Key Security — Algorithm Selection and Rotation

Signing keys are the root of trust for every token IdentityServer issues. The default RS256 algorithm is broadly compatible. ES256 (ECDSA) offers smaller tokens and is appropriate for new deployments.

### Automatic Key Management (Recommended)

```csharp
// ✅ Production automatic key management
builder.Services.AddIdentityServer(options =>
{
    // Rotate every 90 days (default); reduce for higher-security deployments
    options.KeyManagement.RotationInterval = TimeSpan.FromDays(90);

    // Announce 14 days before activation so JWKS caches refresh
    options.KeyManagement.PropagationTime = TimeSpan.FromDays(14);

    // Keep retired keys for 14 days to validate recently-issued tokens
    options.KeyManagement.RetentionDuration = TimeSpan.FromDays(14);

    // Delete keys when their retention period ends
    options.KeyManagement.DeleteRetiredKeys = true;

    // Encrypt keys at rest via ASP.NET Core Data Protection (default: true)
    options.KeyManagement.DataProtectKeys = true;

    // Store keys in a shared, durable location for load-balanced deployments
    options.KeyManagement.KeyPath = "/var/identity/keys";

    // ES256 first = default for new tokens; RS256 for legacy client compatibility
    options.KeyManagement.SigningAlgorithms = new[]
    {
        new SigningAlgorithmOptions(SecurityAlgorithms.EcdsaSha256),
        new SigningAlgorithmOptions(SecurityAlgorithms.RsaSha256)
        {
            UseX509Certificate = true
        }
    };
});
```

### Key Storage — ASP.NET Data Protection

Automatic key management encrypts signing keys at rest using ASP.NET Data Protection. Configure Data Protection to use durable, shared storage. See [ASP.NET Co

Related in Security