From b3532442e2026ab2e82e698e23137c8e362fa493 Mon Sep 17 00:00:00 2001 From: Maarten Balliauw Date: Mon, 26 Oct 2026 08:03:51 +0100 Subject: [PATCH 1/5] docs(spaces): document space-path cookie scoping and __Host- restriction --- .../docs/identityserver/spaces/index.mdx | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/astro/src/content/docs/identityserver/spaces/index.mdx b/astro/src/content/docs/identityserver/spaces/index.mdx index 71dab5864..04ca4fb1e 100644 --- a/astro/src/content/docs/identityserver/spaces/index.mdx +++ b/astro/src/content/docs/identityserver/spaces/index.mdx @@ -1,7 +1,7 @@ --- title: "IdentityServer Spaces" description: "Run multiple isolated IdentityServer security domains in a single deployment using Spaces with per-tenant configuration and operational data" -date: 2026-10-23 +date: 2026-10-26 sidebar: label: "Overview" order: 1 @@ -98,6 +98,36 @@ If users must be shared across spaces, use a deliberately separate user director [space-aware User Management storage](/identityserver/data/providers/duende-storage/getting-started.md#use-duende-user-management). ::: +## Cookies and Space Paths + +When a path pattern matches a space, IdentityServer scopes its cookies to that space's path. This keeps sessions in +different spaces on the same origin apart. IdentityServer derives the cookie `Path` on every request from the resolved +base path, which is the hosting `PathBase` plus the matched space path (for example, `/host/space-a`). Spaces matched +by origin only add no path, so their cookies keep `Path=/`. There is nothing to configure. All other cookie attributes +(name, `Domain`, `Secure`, `SameSite`, and `HttpOnly`) come from your configuration unchanged. + +IdentityServer scopes these cookies to the space path: + +* The session cookie, which uses the `idsrv` scheme by default. If you set + `IdentityServerOptions.Authentication.CookieAuthenticationScheme`, or rely on the default authenticate or default + scheme, that scheme's cookie is scoped instead (for example, ASP.NET Core Identity's `Identity.Application`). +* The `idsrv.external` cookie used for external authentication. +* The temporary message cookies that carry state between pages, such as consent. + +Other application cookies, and the correlation and nonce cookies of external authentication handlers such as OpenID +Connect, are not changed. + +:::caution[Don't use the __Host- cookie name prefix with path-based spaces] +The `__Host-` prefix requires `Path=/`. If IdentityServer builds a `__Host-` prefixed cookie for a request whose +resolved path isn't `/`, it throws an `InvalidOperationException` before issuing the cookie. The message reads: +`Cookie '' uses the '__Host-' prefix, which requires the cookie path to be '/', but the resolved IdentityServer +cookie path is ''.` Use the `__Secure-` prefix instead. It still requires the `Secure` attribute but permits +non-root paths. +::: + +Call `UseSpaceResolution()` before `UseIdentityServer()`. If space resolution hasn't run yet, cookies fall back to +`Path=/` and aren't isolated between spaces. + ## What Spaces Does Not Isolate :::caution[Spaces Do Not Isolate Every Process-Level Dependency] From 1049c56bc0562ffded48ee9fb280bfa4d8e4b370 Mon Sep 17 00:00:00 2001 From: Maarten Balliauw Date: Mon, 26 Oct 2026 10:24:07 +0100 Subject: [PATCH 2/5] Update cookie path handling explanation in docs Clarify how IdentityServer handles cookies for spaces matched by origin. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- astro/src/content/docs/identityserver/spaces/index.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/astro/src/content/docs/identityserver/spaces/index.mdx b/astro/src/content/docs/identityserver/spaces/index.mdx index 04ca4fb1e..fb267d0c7 100644 --- a/astro/src/content/docs/identityserver/spaces/index.mdx +++ b/astro/src/content/docs/identityserver/spaces/index.mdx @@ -103,8 +103,9 @@ If users must be shared across spaces, use a deliberately separate user director When a path pattern matches a space, IdentityServer scopes its cookies to that space's path. This keeps sessions in different spaces on the same origin apart. IdentityServer derives the cookie `Path` on every request from the resolved base path, which is the hosting `PathBase` plus the matched space path (for example, `/host/space-a`). Spaces matched -by origin only add no path, so their cookies keep `Path=/`. There is nothing to configure. All other cookie attributes -(name, `Domain`, `Secure`, `SameSite`, and `HttpOnly`) come from your configuration unchanged. +by origin only add no space path, so their cookies use the hosting `PathBase`, or `/` when it is empty. +There is nothing to configure. All other cookie attributes (name, `Domain`, `Secure`, `SameSite`, and `HttpOnly`) come +from your configuration unchanged. IdentityServer scopes these cookies to the space path: From dc52f0494601c56613192fbc802b319f8ad3daaa Mon Sep 17 00:00:00 2001 From: Maarten Balliauw Date: Mon, 2 Nov 2026 12:21:36 +0100 Subject: [PATCH 3/5] docs: spaces cookie rollout impact and check-session cookie --- .../docs/identityserver/spaces/index.mdx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/astro/src/content/docs/identityserver/spaces/index.mdx b/astro/src/content/docs/identityserver/spaces/index.mdx index fb267d0c7..0d33af783 100644 --- a/astro/src/content/docs/identityserver/spaces/index.mdx +++ b/astro/src/content/docs/identityserver/spaces/index.mdx @@ -1,7 +1,7 @@ --- title: "IdentityServer Spaces" description: "Run multiple isolated IdentityServer security domains in a single deployment using Spaces with per-tenant configuration and operational data" -date: 2026-10-26 +date: 2026-11-02 sidebar: label: "Overview" order: 1 @@ -114,6 +114,10 @@ IdentityServer scopes these cookies to the space path: scheme, that scheme's cookie is scoped instead (for example, ASP.NET Core Identity's `Identity.Application`). * The `idsrv.external` cookie used for external authentication. * The temporary message cookies that carry state between pages, such as consent. +* The check-session cookie, `idsrv.session` by default. It takes the same path as the cookies above, so it is scoped to + the space path and your hosting `PathBase`. The name comes from `Authentication.CheckSessionCookieName`. IdentityServer + issues it only when `Endpoints.EnableCheckSessionEndpoint` is enabled. It still uses `Domain` and `SameSite` from + `Authentication.CheckSessionCookieDomain` and `Authentication.CheckSessionCookieSameSiteMode`. Other application cookies, and the correlation and nonce cookies of external authentication handlers such as OpenID Connect, are not changed. @@ -126,6 +130,17 @@ cookie path is ''.` Use the `__Secure-` prefix instead. It still requires non-root paths. ::: +### Rollout Impact + +IdentityServer doesn't migrate existing cookies. Browsers hold cookies issued with `Path=/` by earlier versions, and +IdentityServer now issues and reads cookies with the space path. Those older cookies aren't sent to the space path, so +users with an active session usually have to sign in again after you upgrade. This applies to the session cookie, the +`idsrv.external` cookie, and the `idsrv.session` check-session cookie. + +The old root-path cookies stay in the browser until they expire or the user clears them. IdentityServer doesn't remove +them. Plan the upgrade for a time when signing users out is acceptable. Hosts without a space path, including origin-only +spaces with an empty `PathBase`, keep `Path=/` and aren't affected. + Call `UseSpaceResolution()` before `UseIdentityServer()`. If space resolution hasn't run yet, cookies fall back to `Path=/` and aren't isolated between spaces. From ee3c3eca219678c026f99b64c5b5fbaf13cf6b2f Mon Sep 17 00:00:00 2001 From: Maarten Balliauw Date: Mon, 2 Nov 2026 13:25:02 +0100 Subject: [PATCH 4/5] docs(spaces): correct cookie rollout guidance, root-path cookies are still sent --- .../docs/identityserver/spaces/index.mdx | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/astro/src/content/docs/identityserver/spaces/index.mdx b/astro/src/content/docs/identityserver/spaces/index.mdx index 0d33af783..e638e0cf2 100644 --- a/astro/src/content/docs/identityserver/spaces/index.mdx +++ b/astro/src/content/docs/identityserver/spaces/index.mdx @@ -132,14 +132,23 @@ non-root paths. ### Rollout Impact -IdentityServer doesn't migrate existing cookies. Browsers hold cookies issued with `Path=/` by earlier versions, and -IdentityServer now issues and reads cookies with the space path. Those older cookies aren't sent to the space path, so -users with an active session usually have to sign in again after you upgrade. This applies to the session cookie, the -`idsrv.external` cookie, and the `idsrv.session` check-session cookie. - -The old root-path cookies stay in the browser until they expire or the user clears them. IdentityServer doesn't remove -them. Plan the upgrade for a time when signing users out is acceptable. Hosts without a space path, including origin-only -spaces with an empty `PathBase`, keep `Path=/` and aren't affected. +IdentityServer doesn't migrate or remove existing cookies. Cookies issued with `Path=/` before you enabled path-based +spaces stay in the browser until they expire or the user clears them. Browsers send `Path=/` cookies to every path, +so these older cookies are still sent to requests under each space path. A new space-scoped cookie with the same name +can exist next to them. + +Changing the cookie path alone doesn't end existing sessions. Whether IdentityServer accepts an older cookie depends on +[data protection partitioning](/identityserver/spaces/getting-started.md#before-deployment): + +* In a named space, the partitioned data protector can't read a cookie that was protected before partitioning, so the + user has to sign in again. +* In the Default space, a fallback to the unpartitioned purpose chain can still read the + older cookie, so the existing session can stay valid. +* With `SpacesOptions.PartitionDataProtection` set to `false`, an older cookie can be read in any space. + +Don't rely on path scoping to sign users out. If existing sessions must end when you enable path-based spaces, end them +explicitly, for example by changing the session cookie name. Hosts without a space path, including origin-only spaces +with an empty `PathBase`, keep `Path=/` and aren't affected. Call `UseSpaceResolution()` before `UseIdentityServer()`. If space resolution hasn't run yet, cookies fall back to `Path=/` and aren't isolated between spaces. From 9e8153115da8046c104f3e0c5d8b605930a20ca2 Mon Sep 17 00:00:00 2001 From: Maarten Balliauw Date: Mon, 2 Nov 2026 13:31:21 +0100 Subject: [PATCH 5/5] docs(spaces): __Host- check applies to any non-root cookie path, message is a prefix --- .../src/content/docs/identityserver/spaces/index.mdx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/astro/src/content/docs/identityserver/spaces/index.mdx b/astro/src/content/docs/identityserver/spaces/index.mdx index e638e0cf2..11b95a203 100644 --- a/astro/src/content/docs/identityserver/spaces/index.mdx +++ b/astro/src/content/docs/identityserver/spaces/index.mdx @@ -122,12 +122,13 @@ IdentityServer scopes these cookies to the space path: Other application cookies, and the correlation and nonce cookies of external authentication handlers such as OpenID Connect, are not changed. -:::caution[Don't use the __Host- cookie name prefix with path-based spaces] +:::caution[Don't use the __Host- cookie name prefix with a non-root cookie path] The `__Host-` prefix requires `Path=/`. If IdentityServer builds a `__Host-` prefixed cookie for a request whose -resolved path isn't `/`, it throws an `InvalidOperationException` before issuing the cookie. The message reads: -`Cookie '' uses the '__Host-' prefix, which requires the cookie path to be '/', but the resolved IdentityServer -cookie path is ''.` Use the `__Secure-` prefix instead. It still requires the `Secure` attribute but permits -non-root paths. +resolved cookie path isn't `/`, it throws an `InvalidOperationException` before issuing the cookie. This happens with +path-based spaces, and also with origin-only spaces or apps without Spaces when the hosting `PathBase` isn't empty. +The message starts with: `Cookie '' uses the '__Host-' prefix, which requires the cookie path to be '/', but the +resolved IdentityServer cookie path is ''.` Use the `__Secure-` prefix instead. It still requires the `Secure` +attribute but permits non-root paths. ::: ### Rollout Impact