Skip to content
New Livestream: How Banks Protect Their Apps with FAPI 2.0. Register Now!

IdentityServer Spaces

A space is an isolated IdentityServer environment within one application deployment. Each space has its own configuration and operational data, while the application shares the same process, code and database infrastructure.

Use Spaces when you need to host multiple security domains without operating a separate IdentityServer deployment for each one. Examples include software-as-a-service tenants, regional environments or independently administered business units.

Spaces build on the pooled storage model in Duende Storage. Each space maps to a storage pool, a logical partition within the same database identified by a numeric pool ID. This isolates all configuration and operational data for that space. IdentityServer resolves the current space at the start of a request and routes all subsequent store operations to that pool.

The reserved management pool is separate from every pool that holds IdentityServer data. It stores each space definition, including its matching rules and assigned data pool. The default space uses data pool 0, while configured spaces normally use positive pool IDs. Normal IdentityServer requests never use the management pool as their data pool.

flowchart LR
    admin["ISpaceAdmin"] --> management["Reserved management pool"]
    management --> definitionA["Space A definition"]
    management --> definitionB["Space B definition"]
    default["Default space"] --> pool0["Data pool 0"]
    definitionA --> pool1["Data pool 1"]
    definitionB --> pool2["Data pool 2"]

Use ISpaceAdmin from a protected administration path to create spaces or change their pool assignments. Moving a space to another pool changes which data it sees, so authorize and audit these operations as changes to a security boundary.

A space can match an incoming request by:

  • Origin, such as https://tenant.example.com
  • Path segment, such as /acme under the default /t prefix
  • Both origin and path

Origin claims take precedence so a path cannot route a request away from a space that owns the host. With the default prefix, a space whose path is /acme receives requests under /t/acme. Middleware moves /t/acme to PathBase before ASP.NET Core routing, leaving the remaining path for IdentityServer endpoints.

Requests that explicitly use the space path prefix but do not match a space receive 404 Not Found. By default, other unmatched requests also receive 404 Not Found; you can opt into the default space with FallbackToDefault.

Spaces use the same login, consent, logout and error page implementations. Space resolution runs before ASP.NET Core routing and path-based resolution moves the matched prefix into PathBase. The shared UI routes therefore run within the resolved space and read that space’s configuration and operational stores.

Spaces do not add per-space UI code or branding. To vary UI behavior, inject ISpaceContextAccessor into a scoped UI service, read the resolved SpaceId and load your own space-aware settings. Apply the same pattern to custom services that need space-specific behavior.

User databases and other application-level services are not made space-aware automatically unless they use the shared IStorageFactory. You must isolate or partition them separately when users, profile data, email delivery or other dependencies belong to a specific space.

Your administration system must authorize operators for the specific spaces they manage. Never trust a space identifier supplied by a client without allowing the resolution middleware to validate it against a configured match pattern.