#### [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')

## JwksKeyResolutionOptions Class

How JWKS\-based key resolution finds and refreshes issuers' keys\.

```csharp
public sealed class JwksKeyResolutionOptions
```

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

## JwksKeyResolutionOptions\.CacheLifetime Property {#Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions.CacheLifetime}

How long a fetched key set answers from cache before the next resolution refetches it\.
The hot path of validation performs no network I/O within this lifetime \- the property
the plan demands of the resolver\.

```csharp
public System.TimeSpan CacheLifetime { get; set; }
```

#### Property Value
[System\.TimeSpan](https://learn.microsoft.com/en-us/dotnet/api/system.timespan 'System\.TimeSpan')

## JwksKeyResolutionOptions\.JwksUris Property {#Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions.JwksUris}

Where a named issuer's JWK Set document is, for issuers known when the host is composed\.

```csharp
public System.Collections.Generic.IDictionary<string,System.Uri> JwksUris { get; }
```

#### Property Value
[System\.Collections\.Generic\.IDictionary&lt;](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.idictionary-2 'System\.Collections\.Generic\.IDictionary\`2')[System\.String](https://learn.microsoft.com/en-us/dotnet/api/system.string 'System\.String')[,](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.idictionary-2 'System\.Collections\.Generic\.IDictionary\`2')[System\.Uri](https://learn.microsoft.com/en-us/dotnet/api/system.uri 'System\.Uri')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.idictionary-2 'System\.Collections\.Generic\.IDictionary\`2')

### Remarks
Consulted first, and additive: two consumers in one host \- a back\-channel logout receiver
and a Shared Signals receiver, say \- each add their own issuer without knowing about the
other\. Nothing here is a slot one consumer can occupy: a single\-valued setting makes every
consumer past the first compose a chain by hand, and one that forgets to call the previous
link silently removes another issuer's keys \- a token that used to verify starts failing its
signature, which reads as an attack rather than as wiring\.

<b>Filled in code, never from a configuration file.</b> An issuer identifier is a URL, and
            the ':' in it is the configuration hierarchy delimiter - so an entry written in appsettings
            binds as nested sections and this map stays empty, with no exception and no log. Every
            issuer then falls through to the well-known convention, which is the same silent
            wrong-document outcome this map exists to prevent. Environment variables are worse, the
            '__' delimiter notwithstanding.

Concurrent by construction, because the resolver reads it on the validation path while a
host may still be adding to it - a receiver that learns an issuer at run time is exactly
the case the selector below describes, and a plain dictionary written during a read is a
torn read or a hang rather than an error.

## JwksKeyResolutionOptions\.RolloverRefetchCooldown Property {#Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions.RolloverRefetchCooldown}

The floor between rollover refetches\. A token naming a "kid" the cached set lacks forces
one refetch \- that is how a rotation is noticed before the cache expires \- but a flood of
tokens with a bogus identifier must not turn that courtesy into hammering the issuer, so
within this window the miss answers from cache\.

```csharp
public System.TimeSpan RolloverRefetchCooldown { get; set; }
```

#### Property Value
[System\.TimeSpan](https://learn.microsoft.com/en-us/dotnet/api/system.timespan 'System\.TimeSpan')

## JwksKeyResolutionOptions\.UseDiscoveryDocument Property {#Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions.UseDiscoveryDocument}

Asks the issuer where its keys are, instead of guessing\. When no map entry and no selector
answers for an issuer, the resolver reads "jwks\_uri" out of that issuer's discovery document
at "\{issuer\}/\.well\-known/openid\-configuration" and fetches the keys from there\.

```csharp
public bool UseDiscoveryDocument { get; set; }
```

#### Property Value
[System\.Boolean](https://learn.microsoft.com/en-us/dotnet/api/system.boolean 'System\.Boolean')

### Remarks
Off by default because it changes where an unconfigured issuer's keys come from, and a host
relying on the "\{issuer\}/\.well\-known/jwks\.json" convention must not have that moved under it
by an upgrade\.

What it buys is that the location follows the provider. A hand-written jwks_uri is a snapshot,
and the copies fail one-sidedly: move the key set at the provider and this receiver refuses
every token, while the same application's sign-in keeps working because it re-reads discovery.
The log then says the signature does not verify, which reads as a forged token rather than as
a configuration value that aged out, and the two places that disagree are never named.
### Methods

## JwksKeyResolutionOptions\.AddJwksUriSelector\(Func\<string,Uri\>\) Method {#Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions.AddJwksUriSelector(System.Func_string,System.Uri_)}

Adds a way to answer where an issuer's JWK Set document is, for issuers whose location is
learned at run time\. Returning null means "not mine", and resolution carries on\.

```csharp
public Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions AddJwksUriSelector(System.Func<string,System.Uri?> selector);
```
#### Parameters

###### `selector` [System\.Func&lt;](https://learn.microsoft.com/en-us/dotnet/api/system.func-2 'System\.Func\`2')[System\.String](https://learn.microsoft.com/en-us/dotnet/api/system.string 'System\.String')[,](https://learn.microsoft.com/en-us/dotnet/api/system.func-2 'System\.Func\`2')[System\.Uri](https://learn.microsoft.com/en-us/dotnet/api/system.uri 'System\.Uri')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.func-2 'System\.Func\`2') {#Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions.AddJwksUriSelector(System.Func_string,System.Uri_).selector}

Answers for the issuers it knows, null for the rest\.

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

### Remarks
The escape hatch beside [JwksUris](https://www.abblix.com/en/docs/api/abblix-securityevents/Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions#Abblix.SecurityEvents.Infrastructure.JwksKeyResolutionOptions.JwksUris 'Abblix\.SecurityEvents\.Infrastructure\.JwksKeyResolutionOptions\.JwksUris'), for a location that cannot be written down
when the host is composed \- a Shared Signals transmitter advertises its "jwks\_uri" in the
ssf\-configuration document, and that value, not a convention, is authoritative for it\.

Additive for the same reason the map is, and by the same reasoning: two receivers, each
learning its own transmitter's metadata, are the ordinary case rather than an exotic one. A
settable delegate would make the second one discard the first, and the loss shows up as a
signature that stopped verifying.

Answering null rather than throwing is what lets the selectors after it, and then the
convention, still run: a delegate that threw for an issuer it did not recognise would take
the fallback out for every other issuer, since nothing runs past a throw.
