IdentityServer Deployment, Proxies, and Production Readiness
When to Use This Skill
- Deploying IdentityServer behind a reverse proxy or load balancer
- Configuring ASP.NET Core Data Protection for production persistence
- Implementing health checks for monitoring IdentityServer instances
- Setting up distributed caching for multi-instance deployments
- Configuring OpenTelemetry for metrics, traces, and logs
- Troubleshooting common deployment issues (HTTPS downgrade, cookie problems, key rotation failures)
- Understanding the difference between Data Protection keys and IdentityServer signing keys
- Setting up logging and events for production monitoring
Docs: https://docs.duendesoftware.com/identityserver/deployment
Deployment Architecture
IdentityServer is ASP.NET Core middleware. It can be hosted with the same diversity of technology as any ASP.NET Core application:
- Hosting: On-premises, cloud (Azure, AWS, GCP), containers, Kubernetes
- Web servers: Kestrel, IIS, Nginx, Apache
- Artifacts: Files, containers (no Dockerfile needed with
dotnet publish /t:PublishContainer) - Scaling: Horizontal with load balancers; requires shared state for multi-instance
Reverse Proxy and Load Balancer Configuration
The Problem
When IdentityServer runs behind a proxy that terminates TLS or changes the originating IP, the middleware sees incorrect request information. This causes:
- HTTPS requests downgraded to HTTP
- HTTP issuer published in
.well-known/openid-configurationinstead of HTTPS - Incorrect host names in discovery document or redirects
- Cookies missing the
Secureattribute (breaksSameSitebehavior)
Solution: ForwardedHeaders Middleware
Most proxies set X-Forwarded-For and X-Forwarded-Proto headers. Configure ASP.NET Core to read them.
Option 1: Environment Variable (Simplest)
Set ASPNETCORE_FORWARDEDHEADERS_ENABLED=true. This automatically adds the middleware and accepts forwarded headers from any single proxy. Best for cloud-hosted environments and Kubernetes.
Option 2: Explicit Configuration (More Control)
Important: The ForwardedHeaders middleware must run early in the pipeline, before IdentityServer middleware and ASP.NET authentication middleware.
Default KnownNetworks
By default, KnownNetworks and KnownProxies support localhost (127.0.0.1/8 and ::1). This is useful for local development or when the proxy and .NET host are on the same machine. In production, configure the actual proxy addresses.
ASP.NET Core Data Protection
Cross-cutting concern: Data protection is critical for all Duende products — both IdentityServer and BFF. See ASP.NET Core Data Protection for comprehensive guidance covering all Duende SDKs.
Why It Matters
Data Protection is critical for IdentityServer. It encrypts and signs sensitive data including:
- Signing keys at rest (when automatic key management is used)
- Persisted grants at rest
- Server-side session data at rest
- State parameters for external OIDC providers
- UI message payloads (logout context, error context)
- Authentication session cookies
- Anti-forgery tokens
Production Configuration
Critical Rules
- Always persist keys to durable storage using a
.PersistKeysTo...()method - Ensure the storage itself is durable — e.g., if using Redis, configure Redis persistence (RDB/AOF)
- Always set an explicit application name with
.SetApplicationName()to prevent key isolation issues - Share keys across all load-balanced instances
- Consider a key escrow sink — for backup/restore of corrupted data protection keys, configure an
IXmlEncryptor-based escrow
Data Protection Keys vs Signing Keys
Both are critical secrets. Losing either causes failures.
Common Data Protection Problems
Symptoms of Data Protection Failure
CryptographicExceptionin logs- Error messages like "Error unprotecting key with kid {Signing Key ID}"
- "The key {Data Protection Key ID} was not found in the key ring"
- Automatic signing key management fails silently
IdentityServer Data Stores for Multi-Instance
Configuration Data
For multi-instance deployments, configuration data must be shared:
Operational Data
Operational data must always be shared in multi-instance deployments:
- Authorization codes, tokens, consent — via persisted grant store
- Signing keys — via
ISigningKeyStore(EF operational store or custom) - Server-side sessions — via
IServerSideSessionStore
Use Entity Framework Core or a persistent cache like Redis.
Distributed Caching
Some optional features require ASP.NET Core's IDistributedCache:
Configure a distributed cache for multi-instance deployments:
Health Checks
Discovery Endpoint Health Check
Tests that IdentityServer can process requests and communicate with the configuration store:
JWKS Health Check
Tests that IdentityServer can access its signing keys:
Note: Finding endpoints by name requires IdentityServer v6.3+.
OpenTelemetry Integration
IdentityServer emits traces, metrics, and logs via the .NET OpenTelemetry SDK (added in v6.1, expanded in v7.0).
Setup
Tracing Sources
In production, you may want only Basic tracing. Use all sources during development and troubleshooting.
Key Metrics (v7.0+)
The meter name is Duende.IdentityServer (accessible via Telemetry.ServiceName).
UI Metrics (From Quickstart)
Logging
IdentityServer uses ASP.NET Core's standard ILogger. Logs are written under the Duende.IdentityServer category.
Log Levels
Configuration
In production, default to Warning to avoid excessive log volume.
Filtering Exceptions
OpenTelemetry Log Correlation
Logs written to ILogger in .NET 8+ can be exported to OpenTelemetry traces. Add builder.Logging.AddOpenTelemetry() to correlate logs with trace IDs.
Events System
Events provide higher-level structured data about operations, suitable for APM integration.
Enabling Events
Raising Events
Custom Event Sink
Events work well with structured logging stores like ELK, Seq, or Splunk.
Rate Limiting
Duende IdentityServer has no built-in rate limiting. Assess it for public-facing or multi-tenant deployments. Three combinable approaches:
(a) Network Layer (first line of defense)
Reverse proxy / gateway (nginx, Azure Application Gateway, AWS API Gateway, Cloudflare). Partitions only by IP/path — coarse, but stops most volumetric abuse before it reaches the app.
(b) ASP.NET Core Rate Limiting Middleware
Register before app.UseIdentityServer():
Critical caveat: IdentityServer matches its protocol endpoints (/connect/authorize, /connect/token, …) with its own middleware, NOT ASP.NET Core endpoint routing. You therefore cannot attach a named per-endpoint policy to protocol endpoints — only the GLOBAL limiter applies to them.
- Approximate per-endpoint limits by partitioning the global limiter on
context.Request.Path. - Named policies (
RequireRateLimiting("...")) still work on your own routed Razor Pages (login/consent). - For the token endpoint, prefer returning a JSON error +
Retry-Afterheader rather than an HTML 429.
(c) Identity-Aware Custom Validator
Implement ICustomTokenRequestValidator — it runs after token request validation, so ClientId/user are known:
Note: It runs after client authentication, secret validation, and DB lookups — so pair it with a coarser layer (a or b) to shed load earlier.
Production Readiness Checklist
Common Anti-Patterns
-
❌ Deploying without configuring ForwardedHeaders behind a reverse proxy
-
✅ Always configure ForwardedHeaders when behind a proxy; test by checking the discovery document's issuer URL
-
❌ Using default (ephemeral) Data Protection keys in production
-
✅ Always persist keys to durable, shared storage with
.PersistKeysTo...() -
❌ Not setting
SetApplicationName()causing key isolation between deployments -
✅ Always set an explicit, consistent application name
-
❌ Using file-system signing key store in containerized/multi-instance deployments
-
✅ Use EF operational store or a shared
ISigningKeyStoreimplementation -
❌ Enabling
TraceorDebuglogging in production — exposes tokens and sensitive data -
✅ Use
Warninglevel in production; useInformationtemporarily for troubleshooting -
❌ Not enabling token cleanup — database grows indefinitely
-
✅ Enable
EnableTokenCleanup = trueand configure appropriate intervals
Common Pitfalls
-
Discovery document shows HTTP issuer: The most common deployment issue. Always configure ForwardedHeaders or the
ASPNETCORE_FORWARDEDHEADERS_ENABLEDenvironment variable when behind a TLS-terminating proxy. -
CryptographicException on startup: Usually means Data Protection keys from one environment are being used in another. Check that keys are persisted correctly and the application name is consistent.
-
Signing keys not shared across instances: The default file-system key store is per-instance. Use
AddOperationalStore()which includesISigningKeyStore, or configure a custom shared store. -
Redis losing Data Protection keys on restart: If using
PersistKeysToStackExchangeRedis, configure Redis with persistence (RDB snapshots or AOF) to survive restarts. -
IIS Data Protection permissions: IIS may lack permissions to persist Data Protection keys. Follow Microsoft's IIS-specific Data Protection documentation.
-
Multiple proxies in chain: If you have more than one proxy, set
ForwardLimitto match the number of proxies, and add all proxy addresses toKnownProxiesorKnownNetworks. -
Cookie SameSite failures behind proxy: If the proxy strips HTTPS, cookies won't get the
Secureattribute, causingSameSite=Nonecookies to be rejected by browsers. Fix the proxy configuration first. -
OpenTelemetry trace source selection: In production, subscribing to all trace sources (
Stores,Validation, etc.) can generate excessive trace data. Start withBasicand add more sources as needed for troubleshooting. -
v8 license key format / runtime enforcement: The v8 license key is a signed JWT with a
kidheader. A v7-format key still runs v8 core, but a v8 key fails on v7/earlier or the BFF runtime withIDX10503: ... Token does not have a kid.v8 also throws at startup when a configured license lacks the entitlement for Server-Side Sessions, Automatic Key Management, or SAML — run lower environments with the production key so gaps surface before production.
Related Skills
identityserver-hosting-setup— DI registration and middleware pipelineidentityserver-data-storage— EF Core stores, migrations, token cleanupidentityserver-aspire— orchestrating IdentityServer in Aspire AppHost


