Skip to content

Commit e980773

Browse files
committed
Add IdentityServer 8.0 documentation
Add comprehensive docs for all user-facing changes in IdentityServer 8.0: New content: - Upgrade guide (v7.4 → v8.0) covering .NET 10, IClock→TimeProvider, CancellationToken on all interfaces, __Host- cookie prefix, HTTP 303 redirects, and GetAllClientsAsync - SAML 2.0 IdP section (overview, configuration, service providers, endpoints, extensibility) - Conformance report documentation - BFF IUserEndpointClaimsEnricher extensibility page - SAML service provider store reference Updated reference pages: - Authentication options (CookieName, ExternalCookieName) - DI registration (SAML, conformance report services) - Token creation service (TimeProvider + CancellationToken) - All 9 store interfaces (CancellationToken parameter) - Client store (GetAllClientsAsync) - DPoP proof validator context - FAPI 2.0 (HTTP 303, conformance report) - ASP.NET Identity cookie schemes (__Host- prefix + migration) Tracking issue: DuendeSoftware/issues#1398
1 parent c0bbc9c commit e980773

30 files changed

Lines changed: 2694 additions & 536 deletions

.weave/plans/is8-docs.md

Lines changed: 791 additions & 0 deletions
Large diffs are not rendered by default.

astro/src/content/docs/bff/extensibility/index.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ redirect_from:
1414

1515
Duende.BFF can be extended in the following areas
1616

17-
* custom logic at the session management endpoints
18-
* custom logic and configuration for HTTP forwarding
19-
* custom data storage for server-side sessions and access/refresh tokens
17+
- custom logic at the session management endpoints
18+
- custom logic and configuration for HTTP forwarding
19+
- custom data storage for server-side sessions and access/refresh tokens
20+
- [enriching claims returned from the user endpoint](/bff/extensibility/user-endpoint-claims/) using `IUserEndpointClaimsEnricher` (added in v8.0)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
title: "User Endpoint Claims Enrichment"
3+
description: Documentation for the IUserEndpointClaimsEnricher interface which allows enriching or replacing the claims returned from the BFF user endpoint.
4+
sidebar:
5+
label: User Claims
6+
order: 20
7+
badge:
8+
text: New
9+
variant: tip
10+
---
11+
12+
The `IUserEndpointClaimsEnricher` interface allows you to enrich or replace the claims returned from the
13+
[BFF user endpoint](/bff/apis/local/). This is useful when you need to add custom claims derived from
14+
external data sources, including data fetched using the user's access token.
15+
16+
## Comparison with IClaimsTransformation
17+
18+
ASP.NET Core's built-in `IClaimsTransformation` runs _during_ the authentication process, before a fully
19+
authenticated principal is available. This means you cannot use the access token at that point to call
20+
external APIs.
21+
22+
`IUserEndpointClaimsEnricher` runs _after_ authentication is complete and gives you access to the full
23+
`AuthenticateResult`, including the access token. This makes it possible to call downstream APIs using
24+
`AccessTokenManagement` to fetch additional user data.
25+
26+
## Interface
27+
28+
```csharp
29+
namespace Duende.Bff.Endpoints;
30+
31+
public interface IUserEndpointClaimsEnricher
32+
{
33+
/// <summary>
34+
/// Enrich the claims for the user endpoint. You can return the same claims,
35+
/// a modified set of claims, or completely new claims.
36+
/// </summary>
37+
/// <param name="authenticateResult">The result from the authentication endpoint.</param>
38+
/// <param name="claims">The current set of claims to be returned.</param>
39+
/// <param name="ct">Cancellation token.</param>
40+
/// <returns>The updated list of claims.</returns>
41+
Task<IReadOnlyList<ClaimRecord>> EnrichClaimsAsync(
42+
AuthenticateResult authenticateResult,
43+
IReadOnlyList<ClaimRecord> claims,
44+
CancellationToken ct = default);
45+
}
46+
```
47+
48+
## Registration
49+
50+
Register your implementation via the DI container:
51+
52+
```csharp
53+
builder.Services.AddTransient<IUserEndpointClaimsEnricher, MyClaimsEnricher>();
54+
```
55+
56+
## Example Implementation
57+
58+
```csharp
59+
public class MyClaimsEnricher : IUserEndpointClaimsEnricher
60+
{
61+
public async Task<IReadOnlyList<ClaimRecord>> EnrichClaimsAsync(
62+
AuthenticateResult authenticateResult,
63+
IReadOnlyList<ClaimRecord> claims,
64+
CancellationToken ct = default)
65+
{
66+
var enriched = claims.ToList();
67+
68+
// Add a custom claim
69+
enriched.Add(new ClaimRecord("custom_claim", "custom_value"));
70+
71+
// You can also access the access token from the AuthenticateResult
72+
// to call downstream APIs for additional user data:
73+
// var token = authenticateResult.Properties?.GetTokenValue("access_token");
74+
75+
return enriched;
76+
}
77+
}
78+
```

astro/src/content/docs/identityserver/aspnet-identity/schemes.md

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ When a user logs in, their identity is established and persisted across requests
1616

1717
When using IdentityServer without ASP.NET Identity, the default cookie scheme is named `"idsrv"`, though we recommend using the constant `IdentityServerConstants.DefaultCookieAuthenticationScheme` in your code if you ever need it.
1818

19+
Starting in **v8.0**, the default cookie name (not the scheme name) has changed to `"__Host-idsrv"` to improve security. The scheme name remains `"idsrv"`. See [Cookie Name Migration (v8.0)](#cookie-name-migration-v80) below for upgrade instructions.
20+
1921
The default cookie scheme is configured by default in `AddIdentityServer()`, which sets up the cookie authentication handler with this scheme name. This cookie is essential for:
2022

2123
- maintaining the user's authenticated session
@@ -39,7 +41,7 @@ services.ConfigureApplicationCookie(options =>
3941
{
4042
// The default ("Identity.Application")
4143
options.Cookie.Name = IdentityConstants.ApplicationScheme;
42-
44+
4345
// Configure other options here...
4446
options.ExpireTimeSpan = TimeSpan.FromHours(1);
4547
options.SlidingExpiration = true;
@@ -57,6 +59,8 @@ This allows your login logic to read the claims from the external provider befor
5759

5860
IdentityServer always uses the `"idsrv.external"` scheme here, available in the `IdentityServerConstants.ExternalCookieAuthenticationScheme` constant.
5961

62+
Starting in **v8.0**, the default cookie _name_ for this scheme has changed to `"__Host-idsrv.external"` (previously `"idsrv.external"`). See [Cookie Name Migration (v8.0)](#cookie-name-migration-v80) below for upgrade instructions.
63+
6064
### Check Session Cookie
6165

6266
IdentityServer session management requires a separate cookie to monitor the session state without sending the large authentication cookie.
@@ -66,6 +70,59 @@ The [User Session Service](/identityserver/reference/services/user-session-servi
6670

6771
Note this cookie is not marked as `HttpOnly`, so it can be accessed in client-side code. The JavaScript code that is required to check user sessions in the background also requires access to this cookie, and needs it to be `HttpOnly`.
6872

73+
## Cookie Name Migration (v8.0)
74+
75+
In IdentityServer v8.0, the default cookie **names** changed to use the `__Host-` prefix:
76+
77+
| Cookie | Old name (v7.x) | New name (v8.0) |
78+
| -------------------- | ---------------- | ----------------------- |
79+
| Primary auth cookie | `idsrv` | `__Host-idsrv` |
80+
| External auth cookie | `idsrv.external` | `__Host-idsrv.external` |
81+
82+
Note: the authentication **scheme names** (`"idsrv"` and `"idsrv.external"`) are unchanged.
83+
84+
### Why `__Host-`?
85+
86+
The `__Host-` prefix is a browser security feature that restricts a cookie to:
87+
88+
- HTTPS-only connections
89+
- `Path=/` (the entire site)
90+
- No `Domain` attribute (preventing subdomain sharing)
91+
92+
This provides defense-in-depth against cookie theft and session fixation attacks.
93+
94+
### Migrating Existing Sessions
95+
96+
To avoid invalidating existing user sessions when upgrading, use the migration middleware to
97+
transparently accept both old and new cookie names. Add it to `Program.cs` **before**
98+
`UseIdentityServer()`, calling it once per cookie:
99+
100+
```csharp
101+
// Program.cs — add BEFORE UseIdentityServer()
102+
app.MigrateIdentityServerCookieName("idsrv", "__Host-idsrv");
103+
app.MigrateIdentityServerCookieName("idsrv.external", "__Host-idsrv.external");
104+
app.UseIdentityServer();
105+
```
106+
107+
When a user visits with an old cookie, the middleware transparently re-issues it under the new
108+
name. Once all active sessions have been re-issued, you can remove the middleware calls.
109+
110+
### Configuring Cookie Names
111+
112+
Override the default names using `AuthenticationOptions`:
113+
114+
```csharp
115+
builder.Services.AddIdentityServer(options =>
116+
{
117+
// Restore legacy names if needed (e.g., staged migration)
118+
options.Authentication.CookieName = "idsrv";
119+
options.Authentication.ExternalCookieName = "idsrv.external";
120+
});
121+
```
122+
123+
See the [upgrade guide](/identityserver/upgrades/v7_4-to-v8_0/#cookie-names-changed-to-__host--prefix)
124+
for full migration instructions.
125+
69126
## Common Pitfalls
70127

71128
- **Mixing Schemes:** Attempting to `SignOutAsync("idsrv")` when ASP.NET Identity is in use will have no effect on the actual `"Identity.Application"` cookie, leaving the user logged in. Always use the constants or the helper services (like `SignInManager`) that match your configuration.
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
---
2+
title: "Conformance Report"
3+
sidebar:
4+
label: Conformance Report
5+
order: 50
6+
badge:
7+
text: v8.0
8+
variant: tip
9+
---
10+
11+
The conformance report assesses your IdentityServer deployment against
12+
[OAuth 2.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1) and
13+
[FAPI 2.0 Security Profile](https://openid.net/specs/fapi-2_0-security-profile.html) specifications,
14+
generating an HTML report accessible via a protected endpoint.
15+
16+
## Installation
17+
18+
Install the NuGet package:
19+
20+
```bash
21+
dotnet add package Duende.IdentityServer.ConformanceReport
22+
```
23+
24+
## Setup
25+
26+
### 1. Register the Conformance Report
27+
28+
Call `AddConformanceReport()` on the IdentityServer builder:
29+
30+
```csharp
31+
builder.Services.AddIdentityServer()
32+
.AddConformanceReport(options =>
33+
{
34+
options.Enabled = true;
35+
});
36+
```
37+
38+
### 2. Map the Endpoint
39+
40+
Add the conformance report endpoint to your middleware pipeline:
41+
42+
```csharp
43+
app.MapConformanceReport();
44+
```
45+
46+
### 3. Access the Report
47+
48+
Navigate to: `https://your-server/_duende/conformance-report`
49+
50+
The endpoint requires an authenticated user by default (see [Authorization](#authorization) below).
51+
52+
## Configuration Options
53+
54+
`ConformanceReportOptions` controls the conformance report feature:
55+
56+
| Property | Type | Default | Description |
57+
| ------------------------------- | ------------------------------------- | --------------------------- | ---------------------------------------------------------------- |
58+
| `Enabled` | `bool` | `false` | Enable or disable the conformance report endpoint. |
59+
| `EnableOAuth21Assessment` | `bool` | `true` | Include OAuth 2.1 profile assessment in the report. |
60+
| `EnableFapi2SecurityAssessment` | `bool` | `true` | Include FAPI 2.0 Security Profile assessment in the report. |
61+
| `PathPrefix` | `string` | `"_duende"` | URL path prefix for the conformance endpoint (no leading slash). |
62+
| `ConfigureAuthorization` | `Action<AuthorizationPolicyBuilder>?` | Requires authenticated user | Authorization policy for the HTML report endpoint. |
63+
| `AuthorizationPolicyName` | `string` | `"ConformanceReport"` | ASP.NET Core authorization policy name used internally. |
64+
| `HostCompanyName` | `string?` | `null` | Optional company name shown in the report header. |
65+
| `HostCompanyLogoUrl` | `Uri?` | `null` | Optional company logo URL shown in the report header. |
66+
67+
## Authorization
68+
69+
By default, the report endpoint requires an authenticated user. Customize the policy using
70+
`ConfigureAuthorization`:
71+
72+
```csharp
73+
// Require a specific role
74+
options.ConfigureAuthorization = policy => policy.RequireRole("Admin");
75+
76+
// Require multiple conditions
77+
options.ConfigureAuthorization = policy => policy
78+
.RequireRole("Admin")
79+
.RequireClaim("department", "IT");
80+
81+
// Allow anonymous (development/testing only)
82+
options.ConfigureAuthorization = policy =>
83+
policy.RequireAssertion(_ => builder.Environment.IsDevelopment());
84+
```
85+
86+
:::caution
87+
If you set `ConfigureAuthorization = null`, you must manually register an ASP.NET Core authorization
88+
policy with the name specified in `AuthorizationPolicyName` (default: `"ConformanceReport"`).
89+
Otherwise, the endpoint will fail at runtime with a "policy not found" error.
90+
:::
91+
92+
## Understanding the Report
93+
94+
The HTML report displays:
95+
96+
- **Server Configuration** — a matrix of server-level conformance rules and their status
97+
- **Client Configurations** — a matrix of per-client conformance rules and their status
98+
- **Rule Legend** — explanation of each rule identifier
99+
- **Notes** — detailed messages for warnings and failures
100+
101+
### Status Indicators
102+
103+
| Symbol | Meaning |
104+
| ------- | -------------------------------------------------------- |
105+
| Pass | Requirement is met |
106+
| Fail | Requirement is not met (configuration is non-conformant) |
107+
| Warning | Recommended practice is not followed |
108+
| N/A | Rule is not applicable to this configuration |
109+
110+
## Requirements
111+
112+
The conformance report uses `IClientStore.GetAllClientsAsync` to enumerate all clients for
113+
assessment. Custom `IClientStore` implementations must implement this method (added in v8.0).
114+
See the [upgrade guide](/identityserver/upgrades/v7_4-to-v8_0/#iclientstoregettallclientsasync-now-required)
115+
for details.
116+
117+
## Full Example
118+
119+
```csharp
120+
// Program.cs
121+
122+
builder.Services.AddIdentityServer()
123+
.AddInMemoryClients(Config.Clients)
124+
.AddConformanceReport(options =>
125+
{
126+
options.Enabled = true;
127+
options.EnableOAuth21Assessment = true;
128+
options.EnableFapi2SecurityAssessment = true;
129+
options.HostCompanyName = "Acme Corp";
130+
options.ConfigureAuthorization = policy => policy.RequireRole("ComplianceTeam");
131+
});
132+
133+
// ...
134+
135+
app.MapConformanceReport();
136+
app.UseIdentityServer();
137+
```

astro/src/content/docs/identityserver/diagnostics/index.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,11 @@ systems (APM). They used to have their own different APIs so IdentityServer only
3333
that could be used to call the APM's APIs. Thanks to OpenTelemetry there is now a standardized
3434
way to emit diagnostic information from a process. The events may eventually be deprecated and removed.
3535

36-
[Read More](/identityserver/diagnostics/events.md)
36+
[Read More](/identityserver/diagnostics/events.md)
37+
38+
## Conformance Report
39+
40+
IdentityServer can generate a conformance report that assesses your configuration against OAuth 2.1
41+
and FAPI 2.0 specifications.
42+
43+
[Read More](/identityserver/diagnostics/conformance-report/)

0 commit comments

Comments
 (0)