#### [Abblix\.SecurityEvents](https://www.abblix.com/en/docs/api/abblix-securityevents 'index')
### [Abblix\.SecurityEvents\.Infrastructure](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure 'Abblix\.SecurityEvents\.Infrastructure')

## ServiceCollectionExtensions Class

Wires the package into a host's service collection\. Every registration lets a host
pre\-registration win: the extension supplies defaults, never overrides\.

```csharp
public static class ServiceCollectionExtensions
```

Inheritance [System\.Object](https://learn.microsoft.com/en-us/dotnet/api/system.object 'System\.Object') → ServiceCollectionExtensions
### Methods

## ServiceCollectionExtensions\.AddBackChannelLogoutReceiver\(this IServiceCollection, BackChannelLogoutValidationOptions\) Method {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddBackChannelLogoutReceiver(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,Abblix.SecurityEvents.BackChannelLogout.BackChannelLogoutValidationOptions)}

Registers the receiver of Logout Tokens a provider posts to this application
\(OpenID Connect Back\-Channel Logout 1\.0 Section 2\.6\), as its own named validation profile\.

```csharp
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddBackChannelLogoutReceiver(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, Abblix.SecurityEvents.BackChannelLogout.BackChannelLogoutValidationOptions options);
```
#### Parameters

###### `services` [Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddBackChannelLogoutReceiver(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,Abblix.SecurityEvents.BackChannelLogout.BackChannelLogoutValidationOptions).services}

The service collection\.

###### `options` [BackChannelLogoutValidationOptions](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.BackChannelLogout.BackChannelLogoutValidationOptions 'Abblix\.SecurityEvents\.BackChannelLogout\.BackChannelLogoutValidationOptions') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddBackChannelLogoutReceiver(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,Abblix.SecurityEvents.BackChannelLogout.BackChannelLogoutValidationOptions).options}

What this receiver expects of every Logout Token: the provider as the issuer and this
application's client identifier as the audience\. Registered as the shared instance, so a
host pre\-registering its own wins\.

#### Returns
[Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection')

### Remarks

A Logout Token is a security event token whose profile contradicts the security-event
default on two points, which is what a named profile is for: the default forbids `exp`
where Section 2.6 requires it, and pins the SET's own type where Section 4.1 forbids
requiring any. Both departures go through the reasoned allowance door, so a host reading
its boot log sees which critical defaults this profile does not carry and why.

It sits in this package rather than beside Shared Signals because a logout notification has
no stream: one token, delivered once, from a provider the application already knows. What
it uses is the token and the pipeline, both of which are here.

Registering this is the whole opt-in: an application that does not call it has nothing that
accepts a Logout Token. The host still owes two registrations of its own: an
[ILogoutNotificationSink](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.BackChannelLogout.ILogoutNotificationSink 'Abblix\.SecurityEvents\.BackChannelLogout\.ILogoutNotificationSink'), because Section 2.7 makes locating and clearing the
sessions the RP's and only the RP knows where it keeps them, and key resolution (for
example [AddJwksKeyResolution\(this IServiceCollection, Action&lt;JwksKeyResolutionOptions&gt;\)](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddJwksKeyResolution(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,System.Action_Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions_) 'Abblix\.SecurityEvents\.Infrastructure\.ServiceCollectionExtensions\.AddJwksKeyResolution\(this Microsoft\.Extensions\.DependencyInjection\.IServiceCollection, System\.Action\<Abblix\.SecurityEvents\.Infrastructure\.JwksKeyResolutionOptions\>\)')), because key trust is deployment knowledge. The
request and the response themselves are this package's:
[BackChannelLogoutHandler](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.BackChannelLogout.BackChannelLogoutHandler 'Abblix\.SecurityEvents\.BackChannelLogout\.BackChannelLogoutHandler') reads the posted form and shapes the answer, leaving
a host adapter nothing to decide but how to render it.

Step 8, the replay check, is optional in the specification and taken up here, because the
request carrying the token is unauthenticated and the token is a bearer credential in the
plainest sense. The default cache rides the host's `IDistributedCache`; a deployment
wanting a strictly atomic reservation derives a `ReplayCacheBase` over its own
store's conditional write and registers that, which TryAdd here then leaves alone.

## ServiceCollectionExtensions\.AddDiscoveryKeyResolution\(this IServiceCollection, Action\<JwksKeyResolutionOptions\>\) Method {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddDiscoveryKeyResolution(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,System.Action_Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions_)}

Registers key resolution that asks each issuer where its keys are, reading "jwks\_uri" from
that issuer's discovery document instead of pinning an address at composition time\.

```csharp
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddDiscoveryKeyResolution(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action<Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions>? configure=null);
```
#### Parameters

###### `services` [Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddDiscoveryKeyResolution(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,System.Action_Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions_).services}

The service collection\.

###### `configure` [System\.Action&lt;](https://learn.microsoft.com/en-us/dotnet/api/system.action-1 'System\.Action\`1')[JwksKeyResolutionOptions](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions 'Abblix\.SecurityEvents\.Infrastructure\.JwksKeyResolutionOptions')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.action-1 'System\.Action\`1') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddDiscoveryKeyResolution(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,System.Action_Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions_).configure}

Cache lifetimes and any issuer\-specific overrides, as usual\.

#### Returns
[Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection')

### Remarks
Why an address pinned at composition time is worth removing:
[UseDiscoveryDocument](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions#Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions.UseDiscoveryDocument 'Abblix\.SecurityEvents\.Infrastructure\.JwksKeyResolutionOptions\.UseDiscoveryDocument')\.

A named entry and any selector answer first, so a host that knows better about one issuer
keeps saying so; discovery stands where the well-known guess otherwise stands.

## ServiceCollectionExtensions\.AddDistributedReplayCache\(this IServiceCollection\) Method {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddDistributedReplayCache(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection)}

Registers the replay cache over the host's `IDistributedCache` as the
[IReplayCache](https://www.abblix.com/en/docs/api/abblix-jwt/Abblix.Jwt.ReplayPrevention.IReplayCache 'Abblix\.Jwt\.ReplayPrevention\.IReplayCache')\.

```csharp
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddDistributedReplayCache(this Microsoft.Extensions.DependencyInjection.IServiceCollection services);
```
#### Parameters

###### `services` [Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddDistributedReplayCache(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection).services}

The service collection\.

#### Returns
[Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection')

### Remarks

What it does depends on the path, and the name promises more than one of them delivers. Where a
caller offers a token to be TRUSTED - a DPoP proof, a client assertion, a logout token - the
reservation is read, and a second use of one identifier is refused. On push delivery it is only a
record of what this receiver accepted: `PushDeliveryHandler` writes after the sink and reads
nothing, because RFC 8935 Section 2 lets a transmitter redeliver and
[ISecurityEventSink](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Delivery.ISecurityEventSink 'Abblix\.SecurityEvents\.Delivery\.ISecurityEventSink') answers for that by requiring idempotent processing. Registering
this cache therefore makes deliveries auditable; it does not make a non-idempotent sink safe.

The store itself is the host's choice and is deliberately not registered here:
`AddDistributedMemoryCache()` gives a single-instance receiver process-local
behavior, Redis or another backend gives a scaled-out one a shared memory - the same
registration either way.

How long an identifier is remembered comes from the validation profile rather than from
here, because the retention only makes sense against the freshness window it has to
outlive - see [ReplayRetention](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Validation.SecurityEventTokenValidationOptions#Abblix.SecurityEvents.Validation.SecurityEventTokenValidationOptions.ReplayRetention 'Abblix\.SecurityEvents\.Validation\.SecurityEventTokenValidationOptions\.ReplayRetention'). The
contract itself lives in Abblix.JWT, so a host that also runs the OpenID Connect server
shares one replay store between its DPoP proofs, its client assertions and its events.

## ServiceCollectionExtensions\.AddJwksKeyResolution\(this IServiceCollection, Action\<JwksKeyResolutionOptions\>\) Method {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddJwksKeyResolution(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,System.Action_Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions_)}

Registers JWKS\-based key resolution as the [IIssuerKeyResolver](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Abstractions.IIssuerKeyResolver 'Abblix\.SecurityEvents\.Abstractions\.IIssuerKeyResolver'): issuers'
keys fetched from their published JWK Set documents and cached, with a forced refetch
when a token names a key the cache has never seen\.

```csharp
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddJwksKeyResolution(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action<Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions>? configure=null);
```
#### Parameters

###### `services` [Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddJwksKeyResolution(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,System.Action_Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions_).services}

The service collection\.

###### `configure` [System\.Action&lt;](https://learn.microsoft.com/en-us/dotnet/api/system.action-1 'System\.Action\`1')[JwksKeyResolutionOptions](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions 'Abblix\.SecurityEvents\.Infrastructure\.JwksKeyResolutionOptions')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.action-1 'System\.Action\`1') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddJwksKeyResolution(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,System.Action_Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions_).configure}

Where key sets live and how long they answer from cache; a Shared Signals receiver sets
the URI selector from the transmitter's advertised "jwks\_uri"\.

#### Returns
[Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection')

## ServiceCollectionExtensions\.AddSecurityEvents\(this IServiceCollection, Action\<SecurityEventsOptions\>\) Method {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEvents(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,System.Action_Abblix.SecurityEvents.Infrastructure.SecurityEventsOptions_)}

Registers the security\-event core: the event registry and the default verifier and
signer over the Abblix JWT core\. Validation is NOT wired here \- each consumer creates
its own named profile with [AddSecurityEventValidationProfile\(this IServiceCollection, object, Action&lt;ValidationProfile&gt;\)](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEventValidationProfile(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,object,System.Action_Abblix.SecurityEvents.Infrastructure.ValidationProfile_) 'Abblix\.SecurityEvents\.Infrastructure\.ServiceCollectionExtensions\.AddSecurityEventValidationProfile\(this Microsoft\.Extensions\.DependencyInjection\.IServiceCollection, object, System\.Action\<Abblix\.SecurityEvents\.Infrastructure\.ValidationProfile\>\)')\.

```csharp
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSecurityEvents(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action<Abblix.SecurityEvents.Infrastructure.SecurityEventsOptions>? configure=null);
```
#### Parameters

###### `services` [Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEvents(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,System.Action_Abblix.SecurityEvents.Infrastructure.SecurityEventsOptions_).services}

The service collection\.

###### `configure` [System\.Action&lt;](https://learn.microsoft.com/en-us/dotnet/api/system.action-1 'System\.Action\`1')[SecurityEventsOptions](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.SecurityEventsOptions 'Abblix\.SecurityEvents\.Infrastructure\.SecurityEventsOptions')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.action-1 'System\.Action\`1') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEvents(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,System.Action_Abblix.SecurityEvents.Infrastructure.SecurityEventsOptions_).configure}

Configures the event dictionary and signing\.

#### Returns
[Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection')

### Remarks

This call registers NO validator: validation lives in named profiles, each created by
[AddSecurityEventValidationProfile\(this IServiceCollection, object, Action&lt;ValidationProfile&gt;\)](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEventValidationProfile(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,object,System.Action_Abblix.SecurityEvents.Infrastructure.ValidationProfile_) 'Abblix\.SecurityEvents\.Infrastructure\.ServiceCollectionExtensions\.AddSecurityEventValidationProfile\(this Microsoft\.Extensions\.DependencyInjection\.IServiceCollection, object, System\.Action\<Abblix\.SecurityEvents\.Infrastructure\.ValidationProfile\>\)') from the documented default steps and
owned by the one consumer that names it. There is deliberately no unnamed shared family.
It existed once, and it is the shape that produced the collision this API replaces: two
consumers of security event tokens in one host shaped one family to contradictory demands,
the outcome depended on registration order, and the loser saw every one of its tokens
refused. An unnamed family invites exactly that consumer back - each editor believes the
shared copy is its own - so the ceremony of naming a profile is the point, not a cost.

Two of the defaults ask for more configuration before they resolve, and each fails loudly
naming what is missing: the verifier needs an [IIssuerKeyResolver](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Abstractions.IIssuerKeyResolver 'Abblix\.SecurityEvents\.Abstractions\.IIssuerKeyResolver') - key trust
is deployment knowledge - and the signer needs
[SigningKeySource](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.SecurityEventsOptions#Abblix.SecurityEvents.Infrastructure.SecurityEventsOptions.SigningKeySource 'Abblix\.SecurityEvents\.Infrastructure\.SecurityEventsOptions\.SigningKeySource'), which only a transmitter has. A pure
receiver registers a resolver and never touches signing; a pure transmitter does the
reverse.

## ServiceCollectionExtensions\.AddSecurityEventValidationProfile\(this IServiceCollection, object, Action\<ValidationProfile\>\) Method {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEventValidationProfile(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,object,System.Action_Abblix.SecurityEvents.Infrastructure.ValidationProfile_)}

Creates a NAMED validation profile: a keyed copy of the default step family that
[configure](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEventValidationProfile(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,object,System.Action_Abblix.SecurityEvents.Infrastructure.ValidationProfile_).configure 'Abblix\.SecurityEvents\.Infrastructure\.ServiceCollectionExtensions\.AddSecurityEventValidationProfile\(this Microsoft\.Extensions\.DependencyInjection\.IServiceCollection, object, System\.Action\<Abblix\.SecurityEvents\.Infrastructure\.ValidationProfile\>\)\.configure') edits without touching any other profile, resolvable as a
keyed [ISecurityEventTokenValidator](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Validation.ISecurityEventTokenValidator 'Abblix\.SecurityEvents\.Validation\.ISecurityEventTokenValidator') under [profileKey](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEventValidationProfile(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,object,System.Action_Abblix.SecurityEvents.Infrastructure.ValidationProfile_).profileKey 'Abblix\.SecurityEvents\.Infrastructure\.ServiceCollectionExtensions\.AddSecurityEventValidationProfile\(this Microsoft\.Extensions\.DependencyInjection\.IServiceCollection, object, System\.Action\<Abblix\.SecurityEvents\.Infrastructure\.ValidationProfile\>\)\.profileKey')\.

```csharp
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSecurityEventValidationProfile(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, object profileKey, System.Action<Abblix.SecurityEvents.Infrastructure.ValidationProfile>? configure=null);
```
#### Parameters

###### `services` [Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEventValidationProfile(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,object,System.Action_Abblix.SecurityEvents.Infrastructure.ValidationProfile_).services}

The service collection\.

###### `profileKey` [System\.Object](https://learn.microsoft.com/en-us/dotnet/api/system.object 'System\.Object') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEventValidationProfile(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,object,System.Action_Abblix.SecurityEvents.Infrastructure.ValidationProfile_).profileKey}

The key the profile's validator resolves under\.

###### `configure` [System\.Action&lt;](https://learn.microsoft.com/en-us/dotnet/api/system.action-1 'System\.Action\`1')[ValidationProfile](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.ValidationProfile 'Abblix\.SecurityEvents\.Infrastructure\.ValidationProfile')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.action-1 'System\.Action\`1') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEventValidationProfile(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,object,System.Action_Abblix.SecurityEvents.Infrastructure.ValidationProfile_).configure}

Shapes the profile: step edits, critical declarations, allowances\.

#### Returns
[Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection')

#### Exceptions

[System\.InvalidOperationException](https://learn.microsoft.com/en-us/dotnet/api/system.invalidoperationexception 'System\.InvalidOperationException')  
[AddSecurityEvents\(this IServiceCollection, Action&lt;SecurityEventsOptions&gt;\)](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEvents(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,System.Action_Abblix.SecurityEvents.Infrastructure.SecurityEventsOptions_) 'Abblix\.SecurityEvents\.Infrastructure\.ServiceCollectionExtensions\.AddSecurityEvents\(this Microsoft\.Extensions\.DependencyInjection\.IServiceCollection, System\.Action\<Abblix\.SecurityEvents\.Infrastructure\.SecurityEventsOptions\>\)') has not run, or a profile already exists under this key \-
            re\-shaping an existing profile through a second registration would let two owners edit one
            copy, which is the situation profiles exist to end\.

### Remarks

This exists for the host whose consumers contradict each other. One composed family per
host was enough until two token kinds met in one container: Back-Channel Logout REQUIRES
`exp` and pins `typ` to its own value, a Shared Signals SET forbids the former
and pins the latter differently - so whichever consumer edits the shared family breaks the
other, and the breakage surfaces as every token of the other kind being refused. A named
profile gives each consumer its own copy to shape - and no unnamed shared family exists
to collide over at all.

The copy is taken from the documented DEFAULTS, so a profile owner reasons from the
baseline and no other consumer's decisions can reach it through registration order.
Critical-step accounting is per profile for the same reason - the defaults' critical steps
seed the profile, [AddCriticalStep&lt;TStep&gt;\(\)](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.ValidationProfile#Abblix.SecurityEvents.Infrastructure.ValidationProfile.AddCriticalStep_TStep_() 'Abblix\.SecurityEvents\.Infrastructure\.ValidationProfile\.AddCriticalStep\<TStep\>\(\)') adds to it, and
the guard judges each profile only by its own declarations and allowances.

## ServiceCollectionExtensions\.AddSecurityEventValidationProfileOnce\(this IServiceCollection, string, Action\<ValidationProfile\>\) Method {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEventValidationProfileOnce(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,string,System.Action_Abblix.SecurityEvents.Infrastructure.ValidationProfile_)}

Creates a named validation profile, and only on first sight of its key\.

```csharp
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSecurityEventValidationProfileOnce(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, string profileKey, System.Action<Abblix.SecurityEvents.Infrastructure.ValidationProfile> configure);
```
#### Parameters

###### `services` [Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEventValidationProfileOnce(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,string,System.Action_Abblix.SecurityEvents.Infrastructure.ValidationProfile_).services}

The service collection\.

###### `profileKey` [System\.String](https://learn.microsoft.com/en-us/dotnet/api/system.string 'System\.String') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEventValidationProfileOnce(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,string,System.Action_Abblix.SecurityEvents.Infrastructure.ValidationProfile_).profileKey}

The key the profile's validator resolves under\.

###### `configure` [System\.Action&lt;](https://learn.microsoft.com/en-us/dotnet/api/system.action-1 'System\.Action\`1')[ValidationProfile](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.ValidationProfile 'Abblix\.SecurityEvents\.Infrastructure\.ValidationProfile')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.action-1 'System\.Action\`1') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.AddSecurityEventValidationProfileOnce(thisMicrosoft.Extensions.DependencyInjection.IServiceCollection,string,System.Action_Abblix.SecurityEvents.Infrastructure.ValidationProfile_).configure}

Shapes the profile: its steps, critical declarations, allowances\.

#### Returns
[Microsoft\.Extensions\.DependencyInjection\.IServiceCollection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection 'Microsoft\.Extensions\.DependencyInjection\.IServiceCollection')

### Remarks
A consumer's registration must survive being run twice without doubling its profile\. What
it must NOT survive is somebody else having taken the key first: that is the collision
named profiles exist to end, and the loser sees every one of its tokens refused by a
pipeline shaped for another kind\.

Those two cases look identical from the key alone - a profile is there either way - so this
leaves a marker of its own and reads that instead. A second call by the same registration
finds its marker and does nothing; a foreign profile under the same key leaves no marker,
so the strict registration runs and refuses loudly, naming the key.

## ServiceCollectionExtensions\.UseDefaultPipeline\(this ValidationProfile\) Method {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.UseDefaultPipeline(thisAbblix.SecurityEvents.Infrastructure.ValidationProfile)}

Lays down the documented default pipeline, in its required order: parse, then the cheap
unverified rejections, then the signature, then the checks that read trusted claims\.

```csharp
public static Abblix.SecurityEvents.Infrastructure.ValidationProfile UseDefaultPipeline(this Abblix.SecurityEvents.Infrastructure.ValidationProfile profile);
```
#### Parameters

###### `profile` [ValidationProfile](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.ValidationProfile 'Abblix\.SecurityEvents\.Infrastructure\.ValidationProfile') {#Abblix.SecurityEvents.Infrastructure.ServiceCollectionExtensions.UseDefaultPipeline(thisAbblix.SecurityEvents.Infrastructure.ValidationProfile).profile}

The profile being shaped\.

#### Returns
[ValidationProfile](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.ValidationProfile 'Abblix\.SecurityEvents\.Infrastructure\.ValidationProfile')

### Remarks
For a profile that wants the baseline and departs from it by editing \- the shape most
consumers of a plain SET want\. A profile that judges a different KIND of token lists its own
steps instead, because the departures are then the point rather than the exception, and a
reader should not have to hold this order in mind to know what that profile does\.
