Table of Contents

Class ValidatingSamlServiceProviderStore

Namespace
Fdyay.IdentityServer.Saml.Idp
Assembly
Fdyay.IdentityServer.Saml.dll

Refuses a registered service provider that cannot be served, where it is read.

public sealed class ValidatingSamlServiceProviderStore : ISamlServiceProviderStore
Inheritance
ValidatingSamlServiceProviderStore
Implements
Inherited Members

Remarks

Duende's counterpart to this and a caching decorator are the two store decorators this tree had not built. The reason recorded in 0.61.0 covered both — a caching decorator needs an invalidation story before it needs an implementation — and belonged to only one of them. This one needs no invalidation story at all: it is a pure function of the row it was handed, so it has nothing to go stale. It was also the half closing a real hole rather than saving a dictionary lookup.

On the read rather than at startup, and that is the point of it being a decorator. A registration known at startup could be checked there — 0.70.0 refuses an unusable signing certificate that way — but the registrations here come from an ISamlServiceProviderStore, which a host may back with a database that answers differently tomorrow. A startup check would be the rule applied to the half of the stores whose contents happen to be in memory.

An invalid registration reads as no registration, rather than throwing. That is what it is from every caller's point of view, it is the answer the endpoints already know how to give — they refuse an unknown service provider and raise their own event for it — and it keeps one host's broken registration from turning a sign-on into a 500. The specific reason goes to the log, because the endpoint's refusal can only say the entity id was not found and an operator looking at a registration that plainly exists needs to be told which field is the problem.

Constructors

ValidatingSamlServiceProviderStore(ISamlServiceProviderStore, IOptions<SamlOptions>, ILogger<ValidatingSamlServiceProviderStore>, ISamlServiceProviderConfigurationValidator?, IEventService?)

public ValidatingSamlServiceProviderStore(ISamlServiceProviderStore inner, IOptions<SamlOptions> options, ILogger<ValidatingSamlServiceProviderStore> logger, ISamlServiceProviderConfigurationValidator? validator = null, IEventService? events = null)

Parameters

inner ISamlServiceProviderStore

The store being validated.

options IOptions<SamlOptions>

The SAML options, for the default validator when none is registered.

logger ILogger<ValidatingSamlServiceProviderStore>

Where a refusal's reason is logged.

validator ISamlServiceProviderConfigurationValidator

Decides whether a registration can be served; Duende's seam since 0.117.0.

events IEventService

Where InvalidSamlServiceProviderConfigurationEvent is raised, when there is one.

Fields

InnerStoreKey

The key the wrapped store is registered under.

public const string InnerStoreKey = "Fdyay.IdentityServer.Saml.ServiceProviderStore.Unvalidated"

Field Value

string

Remarks

A key rather than the plain service type, because this wrapper is registered as that type itself. The container still owns the inner store's lifetime and its disposal — the same arrangement DataProtectingPersistedGrantStore uses, and for the same reason.

Methods

FindByEntityIdAsync(string, CancellationToken)

The registration with this entity id, or null when there is none to serve.

public Task<SamlServiceProvider?> FindByEntityIdAsync(string entityId, CancellationToken cancellationToken = default)

Parameters

entityId string

The service provider's entity id, compared exactly.

cancellationToken CancellationToken

Cancels the lookup.

Returns

Task<SamlServiceProvider>

The registration, or null.

Remarks

Null when the inner store has no such provider, when it is disabled, or when the configuration validator refuses it — the last logged with its reason and raised as InvalidSamlServiceProviderConfigurationEvent.

GetAllSamlServiceProvidersAsync(CancellationToken)

Every provider the inner store holds that can be served, a disabled one included. Duende's, measured.

public IAsyncEnumerable<SamlServiceProvider> GetAllSamlServiceProvidersAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

Returns

IAsyncEnumerable<SamlServiceProvider>

Remarks

Each refused registration is logged and raised as it is when it is looked up, and left out.