Table of Contents

Class IdentityServerOptions

Namespace
Fdyay.IdentityServer.Configuration
Assembly
Fdyay.IdentityServer.Core.dll

Top-level configuration for the identity server.

public class IdentityServerOptions
Inheritance
IdentityServerOptions
Inherited Members

Properties

AccessTokenJwtType

The value written to the typ header of JWT access tokens. Defaults to at+jwt, per RFC 9068.

public string AccessTokenJwtType { get; set; }

Property Value

string

Remarks

Identity tokens are unaffected and always use JWT. Change this only for a resource server that rejects the RFC 9068 media type; some older stacks expect the bare JWT here.

Authentication

The cookies this server writes itself, rather than through a framework handler.

public AuthenticationOptions Authentication { get; set; }

Property Value

AuthenticationOptions

BackChannelLogout

Back-channel logout notification behaviour (OpenID Connect Back-Channel Logout 1.0).

public BackChannelLogoutOptions BackChannelLogout { get; set; }

Property Value

BackChannelLogoutOptions

Ciba

Back-channel authentication behaviour (OpenID Connect CIBA Core 1.0).

public CibaOptions Ciba { get; set; }

Property Value

CibaOptions

Cors

CORS settings for the protocol endpoints.

public CorsOptions Cors { get; set; }

Property Value

CorsOptions

Csp

Content-Security-Policy for the pages and iframes this server serves.

public CspOptions Csp { get; set; }

Property Value

CspOptions

DPoP

Options for DPoP (RFC 9449).

public DPoPOptions DPoP { get; set; }

Property Value

DPoPOptions

DeviceFlow

Device authorization grant behaviour (RFC 8628).

public DeviceFlowOptions DeviceFlow { get; set; }

Property Value

DeviceFlowOptions

Discovery

Discovery document options.

public DiscoveryOptions Discovery { get; set; }

Property Value

DiscoveryOptions

EmitIssuerIdentificationResponseParameter

Whether an authorization response carries the iss parameter (RFC 9207). Defaults to true.

public bool EmitIssuerIdentificationResponseParameter { get; set; }

Property Value

bool

Remarks

The mix-up defence: a client that talks to more than one authorization server cannot otherwise tell which one a redirect came back from, because the response carries a code and a state and nothing that names its author. On by default, which is a deviation worth being deliberate about — RFC 9207 §2 says an authorization server should send it, and OAuth 2.0 requires a client to ignore response parameters it does not recognise, so emitting it cannot break a client that is not looking for it.

Off is for a host that has found the client this does break, and turning it off also stops discovery advertising it: a client told the parameter is there and then not sent it fails the check that was the point of telling it.

EmitScopesAsSpaceDelimitedStringInJwt

Whether a JWT access token carries scope as one space-delimited string. Defaults to true.

public bool EmitScopesAsSpaceDelimitedStringInJwt { get; set; }

Property Value

bool

Remarks

RFC 9068 §2.2.3 says the claim on an at+jwt access token is "a JSON string containing a space-separated list", and AccessTokenJwtType declares that media type by default — so this is what the token already claims to be doing.

The alternative is not "an array": it is an array or a string depending on how many scopes the client asked for, because the payload builder collapses a single-valued claim to a scalar. A resource server written against a one-scope token reads a string and breaks the day a second scope is added to the client. Off is for a deployment whose resource servers were built against that array and have not been changed yet; it is not a shape this server recommends.

Identity tokens are unaffected: scope is not an identity-token claim.

EmitStaticAudienceClaim

Whether every access token carries a static aud of {issuer}/resources in addition to the audiences of the API resources it was issued for. Off by default: a static audience every token carries is one every resource server has to be told to ignore.

public bool EmitStaticAudienceClaim { get; set; }

Property Value

bool

Remarks

Backwards compatibility only, for deployments whose APIs were built against an older IdentityServer that emitted this audience unconditionally and validate it. It widens the audience of every token, so leave it off unless a resource server actually requires it.

Endpoints

Endpoint enablement flags.

public EndpointsOptions Endpoints { get; set; }

Property Value

EndpointsOptions

Events

Which kinds of event reach the sink. All off by default.

public EventsOptions Events { get; set; }

Property Value

EventsOptions

InputLengths

Bounds on the length of what a caller may send.

public InputLengthRestrictions InputLengths { get; set; }

Property Value

InputLengthRestrictions

IssuerUri

The issuer name (URI). If null, it is inferred from the request origin.

public string? IssuerUri { get; set; }

Property Value

string

JwtValidationClockSkew

How far past its exp a JWT access token this server issued is still accepted. Defaults to Zero.

public TimeSpan JwtValidationClockSkew { get; set; }

Property Value

TimeSpan

Remarks

Zero, and the reason is what clock skew is for. A tolerance exists so that two clocks that disagree do not reject each other — but the token being validated here was minted by this server, and read by this server at UserInfo, at introspection and at a local API. There is one clock, so there is nothing to tolerate, and every second of tolerance is a second in which expires_in did not mean what the token response said it meant.

This is a change of behaviour rather than a new knob: nothing set ClockSkew on the validation parameters, so the value in force was IdentityModel's default of five minutes — a token was accepted for five minutes past the expiry this server had published for it, and no setting anywhere said so.

The two places this server validates a JWT minted by somebody else — a client's request object and a client's authentication assertion — deliberately do not read this. There the two clocks are real and a tolerance is what keeps a client with a drifting clock working.

KeyManagement

Key management options.

public KeyManagementOptions KeyManagement { get; set; }

Property Value

KeyManagementOptions

LogoutTokenJwtType

The value written to the typ header of back-channel logout tokens. Defaults to logout+jwt, per OpenID Connect Back-Channel Logout 1.0 §2.4. Duende's.

public string LogoutTokenJwtType { get; set; }

Property Value

string

Remarks

Change this only for a relying party that rejects the explicit type. Empty writes the token handler's JWT, where Duende's writes no typ at all. A relying party following the specification may refuse a logout token typed anything else, so the default is the one to keep.

LowerCaseIssuerUri

Whether the lowercase issuer name is emitted. Defaults to true.

public bool LowerCaseIssuerUri { get; set; }

Property Value

bool

MutualTls

Mutual-TLS client authentication and certificate-bound tokens (RFC 8705).

public MutualTlsOptions MutualTls { get; set; }

Property Value

MutualTlsOptions

PersistentGrants

What this server does with the grants it persists.

public PersistentGrantOptions PersistentGrants { get; set; }

Property Value

PersistentGrantOptions

PushedAuthorization

Pushed authorization request behaviour (RFC 9126).

public PushedAuthorizationOptions PushedAuthorization { get; set; }

Property Value

PushedAuthorizationOptions

StrictClientAssertionAudienceValidation

Whether every private_key_jwt client assertion is held to the strict rule: typed client-authentication+jwt, with exactly one audience, this server's issuer. Defaults to false.

public bool StrictClientAssertionAudienceValidation { get; set; }

Property Value

bool

Remarks

Duende 8.0.1's, measured from its PrivateKeyJwtSecretValidator, after draft-ietf-oauth-rfc7523bis and the audience-injection findings of 2025: an assertion naming several audiences, or a URL as its audience, can be one a client signed for another server. Off, an assertion may name this server's issuer or the URL it was sent to among its audiences, and its typ is not read — except that an assertion typed client-authentication+jwt is held to the strict rule whatever this says, as in Duende. The issuer is compared ignoring one trailing slash, as Duende compares it. New in 0.176.0; until then this server had no such option, and the parity matrix said its rule was unconditionally strict, which it was not.

StrictJarValidation

Whether a request object must be typed oauth-authz-req+jwt (RFC 9101 §10.8). Defaults to false.

public bool StrictJarValidation { get; set; }

Property Value

bool

Remarks

Duende's, measured from its 8.0.1 package. Not asked of a signed CIBA request, as Duende's CIBA validator does not.

SupportedClientAssertionSigningAlgorithms

The signing algorithms a client authentication assertion (RFC 7523) may use.

public ICollection<string> SupportedClientAssertionSigningAlgorithms { get; }

Property Value

ICollection<string>

Remarks

The same rule at the other door, and the one where it matters more: this assertion is the client's credential. Advertised as token_endpoint_auth_signing_alg_values_supported.

SupportedRequestObjectSigningAlgorithms

The signing algorithms a request object (RFC 9101) may use.

public ICollection<string> SupportedRequestObjectSigningAlgorithms { get; }

Property Value

ICollection<string>

Remarks

Asymmetric only: a request object is a client instructing this server what to do with an authorization request, and it is verified against a key from the client's registration.

Stated rather than inferred, which is the change. Nothing set ValidAlgorithms, so the accepted set was whatever the presented key happened to support — a set no operator could see, narrow, or find written down, and one discovery said nothing about. Discovery now advertises exactly this list, so a client is never told about an algorithm this server would then refuse.

TokenRequestDefaultScopesFromResourceStore

Whether a client_credentials or extension grant token request that names no scope asks for the client's allowed scopes the resource store has, as Duende 8.0.1's does, and is refused when it would be granted none. Defaults to false: the client's allowed scopes as registered, as before.

public bool TokenRequestDefaultScopesFromResourceStore { get; set; }

Property Value

bool

Remarks

Duende's TokenRequestValidator.ValidateRequestedScopesAndResourcesAsync, measured. With it, a request naming no scope from a client with no allowed scopes is invalid_scope; client_credentials asks for the API scopes the store has among them (FindApiScopesByNameAsync), so an identity scope such as openid, or a name the store does not have, is left out rather than refused; an extension grant asks for the identity resources and API scopes the store has among them, and offline_access when the client allows offline access, so it gets a refresh token. And a request of either grant granted no scope at all is invalid_scope, as Duende's ResourceValidationResult.Succeeded requires one — a request naming its scopes is otherwise validated as before. Off by default because each changes what an existing client receives: a refusal becomes a token, a token gains a refresh token, or a token becomes a refusal.

UserInteraction

User interaction (login/consent) options.

public UserInteractionOptions UserInteraction { get; set; }

Property Value

UserInteractionOptions

ValidateTenantOnAuthorization

Whether a session whose tenant claim differs from the request's tenant: hint is sent back to sign in. Defaults to false.

public bool ValidateTenantOnAuthorization { get; set; }

Property Value

bool

Remarks

Duende's name, default and rule, measured from its ProcessLoginAsync.

Validation

Checks this server applies to values it has already accepted from a registration.

public ValidationOptions Validation { get; set; }

Property Value

ValidationOptions