identityserver-stores
Implement and customize Duende IdentityServer stores including configuration store, operational store, and Entity Framework Core integration. Covers migrations, custom store implementations, caching strategies, server-side sessions, signing key storage, token cleanup, and multi-tenant patterns.
What this skill does
# Duende IdentityServer Stores
## When to Use This Skill
- You are wiring up `AddConfigurationStore()` or `AddOperationalStore()` with EF Core and need correct registration, migration assembly setup, and schema configuration.
- You are implementing a custom `IClientStore`, `IResourceStore`, `IPersistedGrantStore`, or `ISigningKeyStore` against a non-EF data source (Redis, Mongo, external API, etc.).
- You need to enable and tune configuration store caching (`AddConfigurationStoreCache()`, expiration windows, distributed cache setup) to reduce database load.
- You are managing EF Core migrations across IdentityServer versions and need to correctly handle schema drift for `ConfigurationDbContext` and `PersistedGrantDbContext`.
- You are enabling server-side sessions (`IServerSideSessionStore`) and need to understand session lifecycle, cleanup, and storage integration.
- You are troubleshooting stale client or resource data, expired token accumulation, or signing key rotation failures tied to store configuration.
- You are designing a multi-tenant IdentityServer deployment and need to choose between database-per-tenant and shared-database store strategies.
## Core Principles
**Store interfaces decouple IdentityServer from persistence.** All data access goes through store interfaces registered in the ASP.NET Core DI container. IdentityServer does not care what database backs them — EF Core, Redis, MongoDB, or a static in-memory collection are all equally valid.
**Two independent store categories exist: configuration and operational.** They can be used independently or together. Configuration data is relatively static (clients, resources, CORS); operational data is dynamic and high-write (grants, sessions, signing keys). They should be sized, cached, and maintained with those distinct access patterns in mind.
**Operational data is protected at rest.** The `Data` payload of persisted grants and serialized signing keys is encrypted using the ASP.NET Core Data Protection API. Key rotation and Data Protection configuration must be coordinated — a lost Data Protection key makes stored grants and signing keys unreadable.
**Consumed grants are soft-deleted, not immediately removed.** One-time-use grants (e.g., authorization codes, one-time refresh tokens) are marked with a `ConsumedTime` rather than deleted. This enables threat detection in custom `IRefreshTokenService` implementations. Do not confuse consumed with expired — the token cleanup service only removes records past their `Expiration`, not consumed ones (unless `RemoveConsumedTokens` is enabled).
**EF Core schema changes are your responsibility.** Duende does not ship automatic migration scripts or schema upgrade tooling. You own migration creation, application, and data migration between IdentityServer versions.
Docs: https://docs.duendesoftware.com/identityserver/data
---
## NuGet Package
```bash
dotnet add package Duende.IdentityServer.EntityFramework
```
This package provides EF Core implementations for all configuration and operational store interfaces.
---
## Store Architecture
IdentityServer's data is split into two categories, each with its own set of store interfaces:
```
┌─────────────────────────────────────────────────────────────┐
│ IdentityServer Runtime │
├──────────────────────────┬──────────────────────────────────┤
│ Configuration Data │ Operational Data │
│ │ │
│ • Clients │ • Authorization codes │
│ • API Resources │ • Reference tokens │
│ • API Scopes │ • Refresh tokens │
│ • Identity Resources │ • User consent │
│ • Identity Providers │ • Device codes │
│ • CORS policies │ • Pushed auth. requests │
│ │ • Signing keys │
│ │ • Server-side sessions │
├──────────────────────────┼──────────────────────────────────┤
│ ConfigurationDbContext │ PersistedGrantDbContext │
│ (IClientStore, │ (IPersistedGrantStore, │
│ IResourceStore, │ IDeviceFlowStore, │
│ IIdentityProviderStore,│ IPushedAuthorizationRequestStore,│
│ ICorsPolicyService) │ IServerSideSessionStore, │
│ │ ISigningKeyStore) │
└──────────────────────────┴──────────────────────────────────┘
```
### Configuration Data
Stores static, rarely-changing data that describes how IdentityServer behaves:
| Interface | Contents |
|---|---|
| `IClientStore` | OAuth/OIDC clients (grant types, redirect URIs, secrets, claims, scopes) |
| `IResourceStore` | `IdentityResource`, `ApiResource`, and `ApiScope` definitions |
| `ICorsPolicyService` | CORS allowed-origin rules (derived from client configuration) |
| `IIdentityProviderStore` | Dynamic external identity provider registrations |
### Operational Data
Stores dynamic, high-write runtime state that IdentityServer creates and manages during request processing:
| Interface | Contents |
|---|---|
| `IPersistedGrantStore` | Authorization codes, refresh tokens, reference tokens, user consent records |
| `IDeviceFlowStore` | Device authorization flow codes and user codes |
| `ISigningKeyStore` | Dynamically managed signing keys (used by automatic key management) |
| `IServerSideSessionStore` | Server-side authentication session data for interactive users |
| `IPushedAuthorizationRequestStore` | Pushed authorization request (PAR) data |
---
## EF Core Integration
The `Duende.IdentityServer.EntityFramework` NuGet package provides EF Core-backed implementations of all store interfaces. It ships two `DbContext` types:
- **`ConfigurationDbContext`** — backs `IClientStore`, `IResourceStore`, `ICorsPolicyService`, `IIdentityProviderStore`
- **`PersistedGrantDbContext`** — backs `IPersistedGrantStore`, `IDeviceFlowStore`, `ISigningKeyStore`, `IServerSideSessionStore`
### Registering Both Stores
```csharp
// ✅ Correct: register both stores with explicit migration assembly
var migrationsAssembly = typeof(Program).Assembly.GetName().Name;
var connectionString = builder.Configuration.GetConnectionString("IdentityServer");
builder.Services.AddIdentityServer()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b =>
b.UseSqlServer(connectionString, sql =>
sql.MigrationsAssembly(migrationsAssembly));
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b =>
b.UseSqlServer(connectionString, sql =>
sql.MigrationsAssembly(migrationsAssembly));
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 3600; // seconds; default 1 hour
});
```
```csharp
// ❌ Wrong: omitting MigrationsAssembly when migrations live in the host project
builder.Services.AddIdentityServer()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(connectionString);
// EF will look for migrations in Duende.IdentityServer.EntityFramework.dll
// and fail to find them
});
```
### Separate Schemas
Isolate configuration and operational tables using `DefaultSchema` to avoid naming collisions and simplify backup strategies:
```csharp
// ✅ Recommended for production: dedicated schemas per store
builder.Services.AddIdentityServer()
.AddConfigurationStore(options =>
{
options.DefaultSchema = "idscfg";
options.ConfigureDbContext = b =>
b.UseSqlServer(connectionString, sql =>
{
sql.MigrationsAssembly(migrationsAssembly);
sql.MigrationsHistoryTable("__ConfigMigrationsHistory", "idscfg");
});
})
.AddOperationalStore(options =>
{
options.DefaultSchema = "idsoRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.