Skip to content

Commit c9d2d9b

Browse files
committed
Address bhazen review feedback: remove platform-only APIs (ISamlServiceProviderAdmin, ServiceProviderEntityId, encryption), fix NameID formats (email+unspecified only), correct ISamlSigninStateStore (in-memory default, EF for prod), rename ISamlSigninInteractionResponseGenerator, update ISamlInteractionService deprecation, add EF Core store docs
1 parent 29264e9 commit c9d2d9b

5 files changed

Lines changed: 70 additions & 273 deletions

File tree

astro/src/content/docs/identityserver/saml/concepts.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ AssertionConsumerServiceUrls = new List<IndexedEndpoint>
9494
}
9595
```
9696

97-
The [`SamlBinding` enum](/identityserver/saml/configuration.md#samlbinding) defines the available binding values. The older `AssertionConsumerServiceBinding` property on `SamlServiceProvider` is obsolete. Do not use it in new code.
97+
The [`SamlBinding` enum](/identityserver/saml/configuration.md#samlbinding) defines the available binding values.
9898

9999
## Profiles
100100

@@ -117,7 +117,7 @@ The three most common formats are:
117117
* **Transient**: a session-scoped, one-time identifier that changes with every SSO session. Use this when the SP does not need to recognize the user across sessions (for example, anonymous access or attribute-only scenarios). Transient identifiers offer the best privacy protection.
118118
* **emailAddress**: the user's email address. Human-readable and easy to work with, but it exposes personally identifiable information (PII) and couples the identifier to a value that can change.
119119

120-
Mismatched NameID format expectations between an IdP and an SP are a common source of SSO failures. In IdentityServer, you configure the supported formats globally via `SamlOptions.SupportedNameIdFormats` and set a per-SP default via `SamlServiceProvider.DefaultNameIdFormat`. For email-format NameIDs, the source claim is controlled by `SamlOptions.EmailNameIdClaimType`. For custom persistent NameID generation, implement [`ISamlNameIdGenerator`](/identityserver/saml/extensibility.md#isamlnameidgenerator). See [SamlOptions](/identityserver/saml/configuration.md#samloptions) for the full configuration reference.
120+
IdentityServer currently supports `email` and `unspecified` NameID formats out of the box. Persistent format support is planned for a future release. For custom NameID generation, implement [`ISamlNameIdGenerator`](/identityserver/saml/extensibility.md#isamlnameidgenerator).
121121

122122
## RelayState
123123

astro/src/content/docs/identityserver/saml/configuration.md

Lines changed: 9 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Available options:
6767
* **`SupportedNameIdFormats`**
6868
Supported NameID formats advertised by the IdP. Defaults to `[ EmailAddress, Unspecified ]`.
6969

70-
The NameID format determines how the user is identified to the SP. **Persistent** identifiers are stable and opaque, suitable when the SP needs to correlate the same user across sessions (for example, account linking). **Transient** identifiers are session-scoped and change with each login, best for privacy-sensitive scenarios where the SP does not need a stable identity. **emailAddress** is human-readable but exposes PII and is coupled to a value that can change. Mismatched format expectations are a common source of SSO failures. See [Name Identifiers](/identityserver/saml/concepts.md#name-identifiers) for a full explanation.
70+
The NameID format determines how the user is identified to the SP. **emailAddress** is human-readable but exposes PII and is coupled to a value that can change. **Unspecified** leaves the format to the IdP's discretion. Persistent and transient formats are planned for a future release. Mismatched format expectations are a common source of SSO failures. See [Name Identifiers](/identityserver/saml/concepts.md#name-identifiers) for a full explanation.
7171

7272
* **`DefaultClockSkew`**
7373
Clock skew tolerance for validating SAML message timestamps. Defaults to 5 minutes.
@@ -92,9 +92,6 @@ Available options:
9292
* **`EmailNameIdClaimType`**
9393
The claim type used to resolve an email-format NameID. Defaults to `ClaimTypes.Email`. Per-SP overrides are set via `SamlServiceProvider.EmailNameIdClaimType`.
9494

95-
* **`SigninStateCookieName`**
96-
Name of the cookie used to store SAML sign-in state between the initial request and the callback. Defaults to `__IdsSvr_SamlSigninState`.
97-
9895
* **`UserInteraction`**
9996
Configures SAML endpoint paths. See [SamlUserInteractionOptions](#samluserinteractionoptions) below.
10097

@@ -159,12 +156,12 @@ builder.Services.AddIdentityServer()
159156
});
160157
```
161158

162-
Use `Saml2Options` when you need to control the IdP's published identity (entity ID), the URL paths it listens on, or the shape of the metadata document it serves to Service Providers. Most deployments only need to set `EntityId`; the remaining defaults are suitable for standard configurations.
159+
Use `Saml2Options` when you need to control the IdP's published identity (entity ID), the URL paths it listens on, or the shape of the metadata document it serves to Service Providers. Most deployments do not need to set `EntityId` explicitly; the default (`{host}/saml`) is suitable for standard configurations.
163160

164161
Available options:
165162

166163
* **`EntityId`** (`string?`)
167-
The SAML entity ID of this IdP. If not set, IdentityServer derives it from the OIDC issuer URL combined with `EntityIdPath`. Defaults to `null`.
164+
The SAML entity ID of this IdP. If not set, IdentityServer derives it from the host URL combined with `EntityIdPath` (resulting in `{host}/saml` by default). Most deployments do not need to set this explicitly. Defaults to `null`.
168165

169166
* **`EntityIdPath`** (`string`)
170167
Path component appended to the OIDC issuer URL when `EntityId` is not explicitly set. Defaults to `/saml`.
@@ -189,14 +186,14 @@ Available options:
189186

190187
## SamlServiceProvider Model
191188

192-
`SamlServiceProvider` represents a registered SAML 2.0 Service Provider. Each SP has its own entity ID, ACS endpoints, signing and encryption certificates, and claim configuration. SPs can be registered statically in code or managed dynamically via the admin API.
189+
`SamlServiceProvider` represents a registered SAML 2.0 Service Provider. Each SP has its own entity ID, ACS endpoints, signing certificates, and claim configuration. SPs can be registered statically in code or managed dynamically via a custom store.
193190

194191
Most properties on `SamlServiceProvider` are optional overrides of the global defaults set in `SamlOptions`. When a property is `null`, the corresponding `SamlOptions` default applies. This lets you configure sensible defaults once and only specify per-SP values where behavior needs to differ.
195192

196193
Available options:
197194

198-
* **`EntityId`** (`ServiceProviderEntityId`)
199-
The SP's entity identifier, as declared in its SAML metadata. Required. Parsed via `ServiceProviderEntityId.Parse("https://sp.example.com", CultureInfo.InvariantCulture)`. See [ServiceProviderEntityId](#serviceproviderentityid) below.
195+
* **`EntityId`** (`string`)
196+
The SP's entity identifier, as declared in its SAML metadata. Required.
200197

201198
* **`DisplayName`** (`string`)
202199
Human-readable name shown in logs and consent screens. Required.
@@ -238,15 +235,6 @@ Available options:
238235
* **`SigningCertificates`** (`ICollection<X509Certificate2>?`)
239236
Certificates used to verify SP-signed messages. Defaults to `null`.
240237

241-
* **`EncryptionCertificates`** (`ICollection<X509Certificate2>?`)
242-
Certificates used to encrypt assertions for this SP. Defaults to `null`.
243-
244-
* **`EncryptAssertions`** (`bool`)
245-
When `true`, assertions are encrypted using `EncryptionCertificates`. Defaults to `false`.
246-
247-
* **`RequireConsent`** (`bool`)
248-
When `true`, the user is always shown a consent screen. Defaults to `false`.
249-
250238
* **`AllowIdpInitiated`** (`bool`)
251239
When `true`, IdP-initiated SSO is allowed for this SP. Defaults to `false`.
252240

@@ -263,72 +251,20 @@ Available options:
263251
Per-SP override for how long issued assertions are valid. Uses `SamlOptions.DefaultAssertionLifetime` when `null`. Defaults to `null`.
264252

265253
* **`AllowedScopes`** (`ICollection<string>`)
266-
Controls which scopes the SP is allowed to request. The requested scopes are resolved to identity resources, defining which claim types are included in the assertion. When empty, all mapped claims are included. Defaults to empty.
254+
Scopes associated with this SP. Used to determine which identity resources (and their claim types) are available for inclusion in assertions. When empty, all mapped claims are included. Defaults to empty.
267255

268256
* **`AuthnContextMappings`** (`Dictionary<string, string>`)
269257
Per-SP override for `acr`/`amr` → `AuthnContextClassRef` URI mappings. Overrides `SamlOptions.DefaultAuthnContextMappings` when set. Defaults to empty.
270258

271259
* **`RequestedClaimTypes`** (`List<string>`)
272-
Claim types this SP expects in assertions. Used to drive claim population for the SP. When both `AllowedScopes` and `RequestedClaimTypes` are configured, the effective set of claims is the intersection: only claim types that are both allowed by scopes and listed here will be included.
260+
Claim types this SP expects in assertions. Used to drive claim population for the SP.
273261

274262
* **`EmailNameIdClaimType`** (`string?`)
275263
Per-SP override for the claim used to resolve an email-format NameID. Uses `SamlOptions.EmailNameIdClaimType` when `null`. Defaults to `null`.
276264

277265
* **`AllowedSignatureAlgorithms`** (`List<string>?`)
278266
Signature algorithms this SP accepts. When `null`, the IdP's default algorithm is used. Defaults to `null`.
279267

280-
## Assertion Signing and Encryption
281-
282-
SAML assertions carry sensitive user identity data (claims, NameIDs, and authentication context) across network boundaries to Service Providers. Signing and encryption protect this data in transit.
283-
284-
**Signing** proves the assertion was issued by this IdP and has not been tampered with. It is always applied (controlled by `SamlSigningBehavior`). See [SamlSigningBehavior](#samlsigningbehavior) for the available options.
285-
286-
**Encryption** wraps the assertion in an XML-Enc envelope using the SP's public key, so only the SP can decrypt and read it. Encryption is optional but recommended when assertions contain sensitive attributes (PII, roles, entitlements) or when the SP is accessed over untrusted networks.
287-
288-
### Enabling Assertion Encryption
289-
290-
Set `EncryptAssertions = true` and provide the SP's encryption certificate on the `SamlServiceProvider`:
291-
292-
```csharp
293-
new SamlServiceProvider
294-
{
295-
EntityId = ServiceProviderEntityId.Parse("https://sp.example.com", CultureInfo.InvariantCulture),
296-
// ...
297-
EncryptAssertions = true,
298-
EncryptionCertificates = new[]
299-
{
300-
X509CertificateLoader.LoadCertificate(
301-
Convert.FromBase64String(spCertificateBase64))
302-
}
303-
}
304-
```
305-
306-
IdentityServer uses the SP's public key (from `EncryptionCertificates`) to encrypt the assertion. The SP uses its corresponding private key to decrypt it. You only need the SP's **public** certificate here, never the private key.
307-
308-
### Certificate Properties
309-
310-
* **`SigningCertificates`** (`ICollection<X509Certificate2>?`)
311-
Certificates used to **verify** SP-signed messages (AuthnRequests). Provide the SP's public signing certificate when `RequireSignedAuthnRequests = true`. Defaults to `null`.
312-
313-
* **`EncryptionCertificates`** (`ICollection<X509Certificate2>?`)
314-
Certificates used to **encrypt** assertions for this SP. Provide the SP's public encryption certificate when `EncryptAssertions = true`. Defaults to `null`.
315-
316-
* **`EncryptAssertions`** (`bool`)
317-
When `true`, assertions are encrypted using `EncryptionCertificates`. Defaults to `false`.
318-
319-
Multiple certificates can be provided to support certificate rotation. IdentityServer will use the first certificate in the list for encryption.
320-
321-
### Certificate Format
322-
323-
Certificates are provided as `X509Certificate2` instances. When loading from Base64-encoded data (e.g., from environment variables or a configuration store):
324-
325-
```csharp
326-
var cert = X509CertificateLoader.LoadCertificate(
327-
Convert.FromBase64String(base64CertificateData));
328-
```
329-
330-
When using the Admin API (`ISamlServiceProviderAdmin`), certificates are passed as `CertificateDto` objects with a `Base64Data` string and an optional `FriendlyName`. See [Service Providers](/identityserver/saml/service-providers.md) for details.
331-
332268
## Enums and Value Types
333269

334270
### SamlBinding
@@ -376,20 +312,6 @@ Properties:
376312
* **`Location`** (`Uri`): The URL of the endpoint.
377313
* **`Binding`** (`SamlBinding`): The HTTP binding the endpoint accepts.
378314

379-
### ServiceProviderEntityId
380-
381-
`ServiceProviderEntityId` is a value object that represents a SAML SP's entity ID string. It provides type safety and validation for entity ID values, preventing raw strings from being used where a validated entity ID is expected.
382-
383-
Parse an entity ID from a string using the static `Parse` method:
384-
385-
```csharp
386-
var entityId = ServiceProviderEntityId.Parse(
387-
"https://sp.example.com",
388-
CultureInfo.InvariantCulture);
389-
```
390-
391-
Use `ServiceProviderEntityId` when setting `SamlServiceProvider.EntityId` in code, or when working with entity IDs returned from the admin API.
392-
393315
### IndexedEndpoint
394316

395317
`IndexedEndpoint` represents a single Assertion Consumer Service (ACS) endpoint on a Service Provider. It extends the basic location-and-binding pair with an index (for ordering when multiple ACS endpoints are registered) and an optional default flag.
@@ -441,7 +363,7 @@ builder.Services.AddIdentityServer(options =>
441363
```csharp
442364
new SamlServiceProvider
443365
{
444-
EntityId = ServiceProviderEntityId.Parse("https://sp.example.com", CultureInfo.InvariantCulture),
366+
EntityId = "https://sp.example.com",
445367
AllowIdpInitiated = true,
446368
// ...
447369
}

0 commit comments

Comments
 (0)