You Just Inherited a Duende IdentityServer. Now What?
Summary: This guide provides a concrete, prioritized 10-step checklist for developers who have inherited a running Duende IdentityServer instance. The steps focus on quickly establishing operational stability and identifying risks. Key actions include verifying the license and expiration, confirming robust Data Protection and Signing Key Management configurations, locating Configuration and Operational data stores, auditing the client inventory, and checking the deployment topology and NuGet packages. The checklist emphasizes that IdentityServer is a standard ASP.NET Core application, making it manageable, and highlights available Duende support resources.
Someone left. A team restructured. Maybe your company acquired another company's codebase. Whatever the reason, you're now looking at a running instance of Duende IdentityServer that you didn't build, and you need to understand it.
Take a breath. You've got this.
Duende IdentityServer is a standard ASP.NET Core application. It uses the same dependency injection, middleware pipeline, configuration system, and hosting model you already know. There's no separate runtime, no mystery JVM, no alien technology. If you've built ASP.NET Core apps before, you already have the foundation. And if you haven't, the patterns are well documented and follow conventions used by the broader .NET ecosystem.
This post walks you through a concrete, prioritized checklist to help you get your bearings. We'll start with the things that could hurt you soonest and work toward the things that will make your life easier over time.
Step 1: Check the License
Your first stop should be the license. Duende IdentityServer requires a license for production use, and licenses have expiration dates.
Where to look:
-
appsettings.jsonorappsettings.Production.jsonfor aLicenseKeyproperty - Environment variables or a secrets manager (Azure Key Vault, AWS Secrets Manager)
-
Program.csorStartup.csfor any custom license loading code - Duende products, such as IdentityServer and the BFF Security Framework, look for a file named
Duende_License.keyin the application's ContentRootPath. If present, the file's contents will be used as the license key.
What to determine:
- Is there a license key at all? Without one, the server runs in trial mode, which is not meant for production.
- When does it expire? Duende sends renewal reminders before expiration, but if the original contact left the company, those emails may have gone to no one.
- What tier is it? The tier determines how many clients you can register and which features are available.
An expired license does not immediately shut down your application. But you lose access to updates, priority support, and you're out of compliance. Check the licensing documentation for specifics on how license enforcement works in your version. If you find that a license has expired or is missing, contact Duende sales to resolve the issue. The team is used to these conversations and will work with you.
Step 2: Understand Data Protection
ASP.NET Core Data Protection is the cryptographic subsystem that protects cookies, anti-forgery tokens, and (critically) IdentityServer's signing keys at rest. It is the single most common source of production issues with IdentityServer deployments. If it's misconfigured, things can break in subtle, painful ways.
What can go wrong:
- Keys stored only in memory are lost on every restart, logging out all users
- Keys stored on local disk aren't shared between load-balanced instances, meaning one node can't decrypt another node's cookies
- Keys not protected at rest can be compromised if the file system is exposed
What to look for in Program.cs:
Three configuration calls matter for production:
Csharp
builder.Services.AddDataProtection()
.PersistKeysToAzureBlobStorage(connectionString, "data-protection", "keys.xml")
.ProtectKeysWithAzureKeyVault(keyIdentifier, credential)
.SetApplicationName("your-identity-server");The three essential calls:
-
PersistKeysTo*()stores keys in shared, durable storage (Azure Blob, AWS Systems Manager, a shared file system, or a database) -
ProtectKeysWith*()encrypts keys at rest (Azure Key Vault, a certificate, or DPAPI on Windows) -
SetApplicationName()creates a logical partition so multiple apps on the same storage don't collide
If any of these are missing, you've found something to fix. The Data Protection guide in the Duende docs walks through every scenario with specific configuration for Azure, AWS, and self-hosted deployments.
Step 3: Verify Signing Key Management
IdentityServer uses cryptographic keys to sign tokens. Relying parties (your APIs, your clients) use the corresponding public keys to verify those tokens. If signing keys go wrong, token validation fails across your entire system.
Automatic vs. static keys:
- Automatic Key Management (the default on most license tiers) handles key creation, rotation, and retirement without intervention. Keys rotate on a schedule, and old keys remain available during a grace period to keep existing tokens valid.
- Static keys are configured manually, often with
AddSigningCredential()orAddValidationKey(). If you see this in your code, someone chose to manage keys by hand. Check whether the certificate or key is approaching expiration. Signing credentials are for the currently active signing key, while validation keys are for validating tokens issued with older keys after a manual rotation.
Quick health check:
Hit the discovery endpoint in your browser:
https://your-identity-server/.well-known/openid-configuration Then follow the jwks_uri link. You should see one or more keys listed. If the keys look stale (you can check kid values over time to see if they rotate), automatic key management may be misconfigured.
What to verify:
- Is the key store shared across all instances? In a load-balanced deployment, every node must read from the same key store. If they don't, tokens signed by one node can't be validated by another.
- Is Data Protection configured correctly? (Step 2 above.) Automatic Key Management uses Data Protection to encrypt keys at rest.
- If using static keys, when do they expire?
Step 4: Identify Your Stores
IdentityServer uses two categories of persistent data:
Configuration data includes clients, API scopes, API resources, and identity resources. This is the "what is allowed" data that defines which applications can request tokens and what permissions are available.
Operational data includes persisted grants (refresh tokens, reference tokens, authorization codes), device codes, consent records, and server-side sessions. This data changes constantly as users authenticate.
How to figure out what you have:
Look in Program.cs for these patterns:
Csharp
// In-memory configuration (defined in code, changes require redeployment)
builder.Services.AddIdentityServer()
.AddInMemoryClients(Config.Clients)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryIdentityResources(Config.IdentityResources);
// Entity Framework (EF) Core-backed stores (configuration lives in a database)
builder.Services.AddIdentityServer()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b =>
b.UseSqlServer(connectionString);
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b =>
b.UseSqlServer(connectionString);
});
// ASP.NET Core Identity integration
builder.Services.AddIdentityServer()
.AddAspNetIdentity<ApplicationUser>();What this tells you:
- In-memory stores mean all client and resource definitions live in code (often a
Config.csfile). Any configuration change requires a code change and redeployment. This is common in smaller deployments but unlikely for production-deployed instances of Duende IdentityServer; this is worth double-checking if the project transitioned mid-development, as this can cause issues in multi-instance setups or when rebooting an instance. - EF Core stores mean configuration and/or operational data lives in a database. Find the connection string and connect to the database to see what's registered.
- ASP.NET Core Identity means the system handles user authentication through the standard ASP.NET Core Identity framework with its own database.
If your deployment uses EF Core stores, check whether token cleanup is configured. Operational stores grow over time as tokens are issued. Without periodic cleanup, the persisted grants table expands indefinitely:
Csharp
.AddOperationalStore(options =>
{
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 3600; // seconds
});Step 5: Take a Client Inventory
Clients are the applications that request tokens from your IdentityServer. Each web app, mobile app, single-page application (SPA), or machine-to-machine service that authenticates through IdentityServer is registered as a client. The number of registered clients also determines your licensing requirements.
Where to find them:
- In-memory: Look for a
Config.csor similar file that definesIEnumerable<Client> - EF Core: Query the
Clientstable in your configuration database - Admin UI: Some deployments use Rock Solid Knowledge's AdminUI, Skoruba AdminUI, or a similar management interface. Check whether one exists.
What to document for each client:
-
ClientIdand display name -
AllowedGrantTypes(tells you how the client authenticates: authorization code, client credentials, etc.) -
RedirectUrisandPostLogoutRedirectUris(tells you where users go during auth flows) -
AllowedScopes(tells you what resources the client can access) - Whether the client has secrets configured and when they were last rotated
-
AllowedCorsOriginsif any clients are browser-based SPAs (misconfigured CORS silently blocks token requests)
This inventory is your map. It tells you which applications depend on this IdentityServer instance and would break if it were to go down.
Step 6: Check the NuGet Packages
Open the .csproj file and look at the Duende package references:
Xml
<PackageReference Include="Duende.IdentityServer" Version="7.1.0" />
<PackageReference Include="Duende.IdentityServer.EntityFramework" Version="7.1.0" /> Critical rule: all Duende packages must be the same major version. Mixing versions (for example, Duende.IdentityServer 7.x with Duende.IdentityServer.EntityFramework 6.x) leads to runtime errors that can be difficult to diagnose.
Also check:
- The target framework. What version of .NET is this running on? If it targets
net6.0ornet7.0, those runtimes are out of support. - Third-party identity packages. Look for packages from Rock Solid Knowledge (SAML, WS-Federation, AdminUI), Sustainsys (SAML2), or others that extend IdentityServer.
If you're running an older version, don't panic. IdentityServer is stable and doesn't stop working because a newer version exists. But you should plan an upgrade path to stay on supported .NET runtimes and receive security patches.
Step 7: Look for Customizations
IdentityServer is highly extensible, and the previous team may have used that extensibility. Customizations change the behavior of the system in ways that won't be obvious from configuration alone.
Common customizations to search for:
-
IProfileServiceimplementation: Controls which claims are included in tokens. Search your codebase forIProfileService. If there's a custom implementation, it's shaping every token your server issues. - Custom grant validators (
IExtensionGrantValidator): Allow non-standard authentication flows. If one exists, it's implementing custom business logic in the token endpoint. - Event sinks (
IEventSink): Capture authentication events for audit logging. Check whether events are being shipped to a logging system like Seq, Application Insights, or an Elasticsearch/Logstash/Kibana (ELK) stack. - Custom stores: If someone implemented
IClientStore,IResourceStore, orIPersistedGrantStoredirectly instead of using the built-in stores, the data source could be anywhere. - Middleware: Check
Program.csfor custom middleware in the pipeline that might intercept or modify requests before they reach IdentityServer.
Each customization you find is a piece of institutional knowledge held by the previous team. Document what you find.
Step 8: Verify Health Checks and Monitoring
If the previous team configured health checks, you have a head start on monitoring. ASP.NET Core health checks are the standard approach:
Csharp
builder.Services.AddHealthChecks()
.AddCheck("discovery", () =>
{
// Verify discovery endpoint is responding
// ...
})
.AddCheck("jwks", () =>
{
// Verify signing keys are accessible
// ...
});Also look for:
- IdentityServer events: Are
RaiseSuccessEvents,RaiseFailureEvents,RaiseInformationEvents, andRaiseErrorEventsset totruein the IdentityServer options? These events are your audit trail. - OpenTelemetry: Newer deployments may be configured with OpenTelemetry for distributed tracing.
- Application Insights or similar application performance monitoring (APM) tool: Check for any monitoring SDK integrations.
If none of this exists, adding health checks and enabling events should be one of your first improvements. The deployment documentation covers health check patterns for monitoring discovery endpoints, signing key availability, and license status.
Step 9: Check Deployment Topology
Understanding how the server is deployed tells you where operational risks live.
Questions to answer:
- How many instances are running? A single instance is a single point of failure. Multiple instances require shared Data Protection keys, shared signing key stores, and shared operational data.
- Is there a reverse proxy? Nginx, Apache, IIS, or a cloud load balancer in front of IdentityServer can introduce header size limits that cause HTTP 431 errors when authentication cookies grow too large.
- Where is it hosted? On-premises, Azure App Service, AWS ECS, Kubernetes, a VM? This determines your deployment and rollback options.
- Is there a continuous integration/continuous deployment (CI/CD) pipeline? Can you deploy changes safely, or is this a "copy files to the server" situation?
- Are there database backups? If operational and configuration data reside in a database, verify that backups exist and that someone has tested their restoration.
Step 10: Build Your Knowledge Base
Now that you've inventoried the system, build up your understanding of the identity concepts behind it.
Essential reading:
- Duende IdentityServer documentation is the primary reference for everything the product does
- Quickstarts walk through building an IdentityServer from scratch, which helps you understand what a "normal" setup looks like
- Troubleshooting guide covers common issues and how to diagnose them
Training options:
- OAuth, OpenID Connect and .NET: The Good Parts is a focused course on the protocol fundamentals
- Identity & Access Control for Modern Applications and APIs goes deeper into implementation patterns
Understanding the protocols behind IdentityServer (OpenID Connect and OAuth 2.0) will pay dividends. You don't need to become a protocol expert, but knowing the basics of authorization code flow, client credentials, refresh tokens, and token validation will make everything else click.
Known Time Bombs to Watch For
Some issues don't announce themselves until they've already caused a problem. Here's what to watch:
| Risk | What Happens | How to Check |
|---|---|---|
| Expired license | No immediate impact, but you lose update and support rights | Check the license key expiration date |
| Data Protection key loss | All users get logged out; tokens become invalid | Verify keys are persisted to durable, shared storage |
| Stale signing keys | If rotation is broken, keys age indefinitely; compromise risk grows | Monitor the JWKS endpoint for key rotation |
| Unbounded token tables | Operational database grows until queries slow down or disk fills | Check EnableTokenCleanup in operational store config |
| Cookie size growth | Adding claims, roles, or external provider data can push cookies past reverse proxy limits | Test with production-like claim sets behind your actual proxy |
| Outdated .NET runtime | .NET 6 and 7 are end-of-life; no security patches | Check TargetFramework in the .csproj |
| Azure SQL + EF Core version mismatch | Specific versions of Microsoft.Data.SqlClient causes severe connection pool issues and CPU spikes on Azure SQL | Check SqlClient version and known issue advisories |
You're Not Alone
Inheriting an identity system can feel overwhelming. It's the security backbone of your entire application ecosystem, and nobody left you a manual. That's a tough spot.
But here's the thing: the system is working right now. Users are logging in. Tokens are being issued. APIs are validating them. You don't need to fix everything today. You need to understand what you have, identify the risks, and make a plan.
Duende support is here. Every license tier includes access to help:
- Community support is available through our developer community forum on GitHub. Our engineering team actively participates. Ask your questions in the open, and you'll get answers from the people who built the product and from the broader community.
- Priority support (included with the Standard, Advanced, and Custom tiers) provides a dedicated email channel with guaranteed response times and direct access to our engineering team. If your inherited deployment has a priority support license, use it. That's exactly what it's for.
For bigger challenges, our partners are ready. When you need an architecture review, implementation help, or someone to dig into a complex codebase, our global network of certified partners specializes in exactly that. These firms know Duende products well and work with organizations of all sizes. Whether you need a few hours of expert guidance or a full implementation engagement, they can meet you where you are.
Your First Week Checklist
Here's a condensed version of everything above. Print it, check things off, and move at whatever pace your situation allows.
- License: Found it? Valid? Know when it expires?
- Data Protection: Keys persisted to shared storage? Protected at rest? Application name set?
- Signing keys: Automatic rotation or static? Shared across instances?
- Stores: In-memory, EF Core, or custom? Where is the database?
- Client inventory: How many clients? What types? Who owns each one?
- NuGet packages: All the same major version? What .NET version?
- Customizations:
IProfileService? Custom grants? Event sinks? - Health checks: Configured? Events enabled? Monitoring in place?
- Deployment: How many instances? Reverse proxy? CI/CD pipeline? Backups?
- Knowledge: Read the docs, run through a quickstart, understand the basics
You didn't choose this situation, but you're the right person to handle it. The technology is solid, the documentation is thorough, and help is available at every level. Take it one step at a time.
You've got this ❤️