identityserver-aspire
Orchestrate Duende IdentityServer in .NET Aspire AppHost — dependency graphs, authority URL wiring, health checks, and multi-instance.
What this skill does
# Orchestrating IdentityServer with .NET Aspire
## When to Use This Skill
Use this skill when:
- Adding Duende IdentityServer to an Aspire-orchestrated solution
- Configuring service dependencies so clients and APIs wait for IdentityServer
- Passing IdentityServer's authority URL to dependent services via Aspire
- Wiring database resources for IdentityServer configuration and operational stores
- Ensuring IdentityServer exposes health checks for Aspire startup ordering
- Adding IdentityServer telemetry sources to Aspire service defaults
- Running multiple IdentityServer replicas in Aspire
- Integration testing an Aspire solution that includes IdentityServer
## Core Principles
1. **IdentityServer is a startup dependency** — Every client app and API depends on IdentityServer being available for discovery, token validation, and OIDC flows. Model this with `WithReference()` + `WaitFor()`.
2. **Explicit configuration over service discovery** — Pass the authority URL, client IDs, and scopes as explicit environment variables. App code reads `IConfiguration`/`IOptions<T>`, never Aspire service discovery.
3. **Health checks enable startup ordering** — Aspire's `WaitFor()` requires the target to expose a healthy health check endpoint. IdentityServer must be configured with health checks for startup ordering to work.
4. **Cross-reference, don't duplicate** — General Aspire and IdentityServer patterns are covered by existing skills. This skill covers only the unique orchestration intersection.
## Related Skills
- `identityserver-hosting-setup` — IdentityServer DI and middleware pipeline
- `identityserver-deployment` — production deployment, data protection, health check implementations
- `identityserver-data-storage` — EF Core stores for configuration and operational data
Docs: https://docs.duendesoftware.com/identityserver/aspire
---
## Pattern 1: AppHost Orchestration Basics
IdentityServer is added to an Aspire AppHost like any ASP.NET Core project. The key
addition is wiring its database dependency so the database is ready before IdentityServer
starts.
```csharp
var builder = DistributedApplication.CreateBuilder(args);
var sqlServer = builder.AddSqlServer("sql");
var identityDb = sqlServer.AddDatabase("identitydb");
var identityServer = builder.AddProject<Projects.IdentityServer>("identity-server")
.WithReference(identityDb)
.WaitFor(sqlServer);
builder.Build().Run();
```
`WaitFor(sqlServer)` ensures the database is accepting connections before IdentityServer
starts. This matters because IdentityServer connects to EF Core stores on startup for
configuration and operational data.
> **Important:** The IdentityServer project itself is a standard ASP.NET Core application.
> See `identityserver-hosting-setup` for DI registration and middleware pipeline setup.
> This skill focuses only on how the AppHost orchestrates it.
---
## Pattern 2: Service Dependency Graph
This is the most critical pattern. Clients and APIs must depend on IdentityServer
because:
- **Clients** download the discovery document (`.well-known/openid-configuration`) at
startup to configure OIDC flows
- **APIs** configured with JWT Bearer authentication download JWKS (signing keys) from
IdentityServer at startup to validate tokens
- **OIDC login redirects** fail if IdentityServer isn't running when a user tries to
sign in
Without explicit dependency ordering, services start in parallel and fail with cryptic
"unable to obtain configuration" errors.
### Full dependency graph
```csharp
var builder = DistributedApplication.CreateBuilder(args);
var sqlServer = builder.AddSqlServer("sql");
var identityDb = sqlServer.AddDatabase("identitydb");
var identityServer = builder.AddProject<Projects.IdentityServer>("identity-server")
.WithReference(identityDb)
.WaitFor(sqlServer);
var api = builder.AddProject<Projects.WeatherApi>("weather-api")
.WithReference(identityServer)
.WaitFor(identityServer);
var webApp = builder.AddProject<Projects.WebApp>("web-app")
.WithReference(identityServer)
.WaitFor(identityServer)
.WithReference(api);
builder.Build().Run();
```
### What each call does
| Call | Effect |
|------|--------|
| `.WithReference(identityServer)` | Makes the IdentityServer endpoint URL available to the dependent service via service discovery |
| `.WaitFor(identityServer)` | Holds the dependent service from starting until IdentityServer's health check returns healthy |
Both are needed. `WithReference` alone provides the URL but doesn't prevent premature
startup. `WaitFor` alone doesn't expose the endpoint URL.
### Dependency flow
```
sqlServer ─► identity-server ─► weather-api
─► web-app ──► weather-api
```
> **Important:** Without `WaitFor(identityServer)`, the API and web app may start before
> IdentityServer is ready, causing `HttpRequestException` when fetching the discovery
> document or JWKS. This leads to `InvalidOperationException: IDX20803: Unable to obtain
> configuration from 'https://.../.well-known/openid-configuration'` errors at startup.
---
## Pattern 3: Authority URL and OIDC Configuration
`WithReference(identityServer)` makes the endpoint available via Aspire service discovery,
but client applications need explicit configuration for the OIDC authority URL, client ID,
and scopes. Use `WithEnvironment` to pass these as standard configuration values.
### Web application (OIDC client)
```csharp
var webApp = builder.AddProject<Projects.WebApp>("web-app")
.WithReference(identityServer)
.WaitFor(identityServer)
.WithEnvironment("Authentication__Authority", identityServer.GetEndpoint("https"))
.WithEnvironment("Authentication__ClientId", "web-app")
.WithEnvironment("Authentication__Scopes__0", "openid")
.WithEnvironment("Authentication__Scopes__1", "profile")
.WithEnvironment("Authentication__Scopes__2", "weather.read");
```
### API (JWT Bearer)
```csharp
var api = builder.AddProject<Projects.WeatherApi>("weather-api")
.WithReference(identityServer)
.WaitFor(identityServer)
.WithEnvironment("Authentication__Authority", identityServer.GetEndpoint("https"));
```
### Issuer URI consideration
By default, IdentityServer infers the issuer URI from incoming requests, which works
correctly within Aspire's network. Only override if the internal URL differs from what
clients see:
```csharp
var identityServer = builder.AddProject<Projects.IdentityServer>("identity-server")
.WithReference(identityDb)
.WaitFor(sqlServer)
.WithEnvironment("IdentityServer__IssuerUri", identityServer.GetEndpoint("https"));
```
> **Important:** Do NOT set `IssuerUri` unless the internal Aspire URL differs from what
> clients see. Mismatched issuer URIs cause token validation failures — the `iss` claim in
> tokens won't match the expected authority.
See `aspire-configuration` for the general pattern of reading these values via `IOptions<T>`
in the app project.
> **When generating app code:** The environment variables above map to standard
> `IConfiguration` keys (`Authentication:Authority`, `Authentication:ClientId`,
> `Authentication:Scopes:0`, etc.). When scaffolding the web app, configure
> `AddOpenIdConnect` to read `Authority` and `ClientId` from
> `builder.Configuration["Authentication:Authority"]` and
> `builder.Configuration["Authentication:ClientId"]`. Bind scopes from the
> `Authentication:Scopes` configuration section. For the API, configure
> `AddJwtBearer` with `options.Authority` from
> `builder.Configuration["Authentication:Authority"]`.
> See `aspnetcore-authentication` for full OIDC and JWT Bearer middleware setup.
> See `aspire-configuration` for the general `IOptions<T>` binding pattern.
---
## Pattern 4: Database and Store Wiring
IdentityServer typically needs its own database for configuration and operational stores.
Other services in the solution use separate databases for application data.
### Separate databases per service
```cshaRelated 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.