Skip to content

Configuration Reference

{
"OpenIddict": {
"Issuer": "https://auth.example.com",
"UseReferenceTokens": false,
"EnableEntityCaching": false,
"RequirePar": false,
"EnableTokenExchange": false,
"Client": {
"AutoRegisterExternalUsers": true,
"Providers": [
{
"Name": "Google",
"ClientId": "xxx.apps.googleusercontent.com",
"ClientSecret": "GOCSPX-xxx",
"Scopes": ["openid", "profile", "email"]
},
{
"Name": "Microsoft",
"ClientId": "00000000-0000-0000-0000-000000000000",
"ClientSecret": "xxx",
"Scopes": ["openid", "profile", "email"]
},
{
"Name": "GitHub",
"ClientId": "Iv1.xxx",
"ClientSecret": "xxx",
"Scopes": ["openid", "user:email"]
}
]
},
"Seeding": {
"Applications": [
{
"ClientId": "my-spa",
"ClientSecret": null,
"DisplayName": "My SPA (PKCE)",
"Permissions": [
"ept:authorization", "ept:token", "ept:logout",
"gt:authorization_code", "gt:refresh_token",
"scp:openid", "scp:profile", "scp:email", "scp:offline_access"
],
"RedirectUris": ["https://app.example.com/callback"],
"PostLogoutRedirectUris": ["https://app.example.com"]
},
{
"ClientId": "my-api",
"ClientSecret": "super-secret-should-come-from-vault",
"DisplayName": "My API (Client Credentials)",
"Permissions": [
"ept:token", "gt:client_credentials", "scp:api"
],
"RedirectUris": [],
"PostLogoutRedirectUris": []
}
],
"Scopes": [
{
"Name": "api",
"DisplayName": "API Access",
"Resources": ["my-api"]
}
]
},
"Passkeys": {
"ServerDomain": "example.com",
"AuthenticatorTimeout": "00:05:00",
"ChallengeSize": 32
}
}
}

Configuration section: OpenIddict

Bound in: GranitOpenIddictModule.ConfigureServices()

PropertyTypeDefaultDescription
IssuerUri?nullExplicit OIDC issuer URI. When null, the issuer is inferred from the incoming request URL. Set explicitly for multi-node deployments behind a load balancer.
UseReferenceTokensboolfalseIssue opaque reference tokens instead of self-contained JWTs. Reference tokens are validated against the database on every API request, enabling instant revocation. Required for SOC2 / ISO 27001 strict compliance. Trade-off: +1 DB round-trip per API call.
EnableEntityCachingboolfalseEnable OpenIddict’s built-in entity caching. Disable in multi-tenant deployments — the cache uses ClientId as the sole key, which causes cross-tenant pollution when two tenants have the same ClientId.
RequireParboolfalseRequire Pushed Authorization Requests (RFC 9126) for all authorization code flows. The /connect/par endpoint is always available; when true, direct authorization requests without a request_uri are rejected. Required for FAPI 2.0 compliance.
EnableTokenExchangeboolfalseEnable OAuth 2.0 Token Exchange (RFC 8693). Registers the urn:ietf:params:oauth:grant-type:token-exchange grant type for microservice delegation and impersonation flows. Clients must have the gt:token_exchange permission.
EnableFapi2ProfileboolfalseEnable the FAPI 2.0 Security Profile. When true, enforces all server-side FAPI 2.0 constraints: RequirePar is set to true, authorization code lifetime is reduced to 60 seconds, and PKCE S256 remains enforced. BFF and resource server must also be configured separately (UseDPoP, ClientAuthenticationMethod: PrivateKeyJwt, RequireDPoP).

Example:

{
"OpenIddict": {
"Issuer": "https://auth.example.com",
"UseReferenceTokens": false,
"EnableEntityCaching": false,
"RequirePar": false,
"EnableFapi2Profile": false
}
}

Configuration section: OpenIddict:Client

Bound in: GranitOpenIddictModule.ConfigureServices()

PropertyTypeDefaultDescription
AutoRegisterExternalUsersbooltrueAuto-create a GranitUser on first login via an external provider. When false, returns 403 if no existing account matches the email.
ProvidersExternalProviderOptions[][]External login providers to configure.
PropertyTypeDefaultDescription
Namestring""Provider name: "Google", "Microsoft", or "GitHub".
ClientIdstring""OAuth 2.0 client ID obtained from the provider’s developer console.
ClientSecretstring""OAuth 2.0 client secret. Use Granit.Vault in production.
Scopesstring[]["openid", "profile", "email"]OAuth scopes to request from the provider.

Example:

{
"OpenIddict": {
"Client": {
"AutoRegisterExternalUsers": true,
"Providers": [
{
"Name": "Google",
"ClientId": "xxx.apps.googleusercontent.com",
"ClientSecret": "GOCSPX-xxx",
"Scopes": ["openid", "profile", "email"]
}
]
}
}
}

Configuration section: OpenIddict:Seeding

Bound in: GranitOpenIddictModule.ConfigureServices() and GranitOpenIddictEntityFrameworkCoreModule.ConfigureServices()

PropertyTypeDefaultDescription
ApplicationsOidcApplicationSeedDescriptor[][]OIDC applications to seed at startup. Idempotent upsert based on ClientId.
ScopesOidcScopeSeedDescriptor[][]OIDC scopes to seed at startup. Idempotent upsert based on Name.
PropertyTypeDescription
ClientIdstringUnique client identifier (upsert key).
ClientSecretstring?Client secret. null for public clients (SPAs). Encrypted before persistence.
DisplayNamestringHuman-readable display name.
Permissionsstring[]OpenIddict permissions (e.g., ept:token, gt:authorization_code, scp:openid).
RedirectUrisstring[]Allowed redirect URIs after authorization.
PostLogoutRedirectUrisstring[]Allowed redirect URIs after logout.
SigningKeyJwkstring?JWK Set containing the client’s public key for private_key_jwt authentication (RFC 7523).
PropertyTypeDescription
NamestringUnique scope name (upsert key).
DisplayNamestringHuman-readable display name.
Resourcesstring[]Resources associated with this scope (audience values).
PrefixMeaningExamples
ept:Endpointept:authorization, ept:token, ept:logout, ept:introspection, ept:revocation, ept:device
gt:Grant typegt:authorization_code, gt:client_credentials, gt:refresh_token, gt:urn:ietf:params:oauth:grant-type:device_code
rst:Response typerst:code, rst:id_token, rst:token
scp:Scopescp:openid, scp:profile, scp:email, scp:roles, scp:offline_access, custom scopes

Example (SPA with PKCE):

{
"ClientId": "my-spa",
"ClientSecret": null,
"DisplayName": "My SPA",
"Permissions": [
"ept:authorization", "ept:token", "ept:logout",
"gt:authorization_code", "gt:refresh_token",
"scp:openid", "scp:profile", "scp:email", "scp:offline_access"
],
"RedirectUris": ["https://app.example.com/callback"],
"PostLogoutRedirectUris": ["https://app.example.com"]
}

Example (M2M with Client Credentials):

{
"ClientId": "my-api",
"ClientSecret": "super-secret-should-come-from-vault",
"DisplayName": "My API",
"Permissions": [
"ept:token", "gt:client_credentials", "scp:api"
],
"RedirectUris": [],
"PostLogoutRedirectUris": []
}

Configuration section: OpenIddict:Passkeys

Bound in: GranitOpenIddictModule.ConfigureServices() and GranitOpenIddictEntityFrameworkCoreModule.ConfigureServices()

PropertyTypeDefaultDescription
ServerDomainstring""WebAuthn Relying Party ID (domain). Required when passkeys are enabled. Must match the domain where the application is hosted (e.g., "example.com").
AuthenticatorTimeoutTimeSpan00:05:00Timeout for authenticator operations (registration and assertion ceremonies).
ChallengeSizeint32Challenge size in bytes for WebAuthn operations.

Example:

{
"OpenIddict": {
"Passkeys": {
"ServerDomain": "example.com",
"AuthenticatorTimeout": "00:05:00",
"ChallengeSize": 32
}
}
}

Bound from: OpenIddict:KeyRotation section

PropertyTypeDefaultDescription
EnabledboolfalseEnable automatic key rotation. When disabled, ephemeral keys are used.
KeyLifetimeTimeSpan90 daysHow long a signing key remains active before rotation.
GracePeriodTimeSpan14 daysHow long a retired key remains in JWKS for token verification. Should be >= max token lifetime.
RotationLeadTimeTimeSpan7 daysHow far in advance a new key is generated before the active key expires.
RsaKeySizeint2048RSA key size in bits. Use 4096 for higher security requirements.
SigningAlgorithmstringRS256The JWT signing algorithm.
{
"OpenIddict": {
"KeyRotation": {
"Enabled": true,
"KeyLifetime": "90.00:00:00",
"GracePeriod": "14.00:00:00",
"RotationLeadTime": "7.00:00:00",
"RsaKeySize": 2048,
"SigningAlgorithm": "RS256"
}
}
}

Configured in: MapOpenIddictEndpoints() lambda

PropertyTypeDefaultDescription
AccountRoutePrefixstring"api/account"Route prefix for account self-service endpoints.
AdminRoutePrefixstring"api/admin"Route prefix for admin management endpoints.
AccountTagNamestring"Account"OpenAPI tag for account endpoints.
AdminTagNamestring"Administration"OpenAPI tag for admin endpoints.

Example:

app.MapOpenIddictEndpoints(options =>
{
options.AccountRoutePrefix = "api/v1/account";
options.AdminRoutePrefix = "api/v1/admin";
});

Static properties for table naming. Must be set before ConfigureServices completes — EF Core caches the compiled model after first use.

PropertyTypeDefaultDescription
DbTablePrefixstring"openiddict_"Table name prefix for all Identity and OpenIddict tables.
DbSchemastring?nullDatabase schema. null uses the provider’s default schema.

Example:

// Before builder.Build()
GranitOpenIddictDbProperties.DbTablePrefix = "auth_";
GranitOpenIddictDbProperties.DbSchema = "identity";

These settings are registered via OpenIddictSettingDefinitionProvider (auto-discovered by GranitSettingsModule) and configurable per-tenant at runtime via the Settings admin API. No redeployment needed.

Setting keyTypeDefaultDescription
OpenIddict.AccessTokenLifetimeTimeSpan01:00:00 (1 hour)Access token lifetime.
OpenIddict.RefreshTokenLifetimeTimeSpan14.00:00:00 (14 days)Refresh token lifetime.
OpenIddict.AuthCodeLifetimeTimeSpan00:05:00 (5 minutes)Authorization code lifetime.
OpenIddict.MaxLoginAttemptsint5Maximum failed login attempts before account lockout.
OpenIddict.IdleSessionTimeoutint0 (disabled)Idle session timeout in minutes. 0 disables the feature.

Setting constants are defined in OpenIddictSettingNames:

public static class OpenIddictSettingNames
{
public const string AccessTokenLifetime = "OpenIddict.AccessTokenLifetime";
public const string RefreshTokenLifetime = "OpenIddict.RefreshTokenLifetime";
public const string AuthCodeLifetime = "OpenIddict.AuthCodeLifetime";
public const string MaxLoginAttempts = "OpenIddict.MaxLoginAttempts";
public const string IdleSessionTimeout = "OpenIddict.IdleSessionTimeout";
}

Feature flags are registered via OpenIddictFeatureDefinitionProvider (auto-discovered by GranitFeaturesModule). Resolution order: Tenant > Plan > Default.

Feature keyDefaultDescription
OpenIddict.TwoFactortrueTOTP-based two-factor authentication.
OpenIddict.DeviceFlowfalseOAuth 2.0 Device Authorization Grant (RFC 8628).
OpenIddict.ExternalLoginstrueExternal login providers (Google, Microsoft, GitHub).
OpenIddict.PkceRequiredtruePKCE requirement for all authorization code flows.
OpenIddict.PasskeysfalseWebAuthn/FIDO2 passwordless authentication.
OpenIddict.JarRequiredfalseRequire JWT-Secured Authorization Requests (RFC 9101).

Feature constants are defined in OpenIddictFeatureNames:

public static class OpenIddictFeatureNames
{
public const string TwoFactor = "OpenIddict.TwoFactor";
public const string DeviceFlow = "OpenIddict.DeviceFlow";
public const string ExternalLogins = "OpenIddict.ExternalLogins";
public const string PkceRequired = "OpenIddict.PkceRequired";
public const string Passkeys = "OpenIddict.Passkeys";
public const string JarRequired = "OpenIddict.JarRequired";
}

All 23 permission constants are defined in OpenIddictPermissions and follow the [Group].[Resource].[Action] convention. They are registered via OpenIddictPermissionDefinitionProvider (auto-discovered by GranitAuthorizationModule).

ConstantValueDescription
OpenIddictPermissions.Users.ReadOpenIddict.Users.ReadList and view users
OpenIddictPermissions.Users.CreateOpenIddict.Users.CreateCreate new users
OpenIddictPermissions.Users.ManageOpenIddict.Users.ManageUpdate user details
OpenIddictPermissions.Users.DeleteOpenIddict.Users.DeleteSoft-delete users
OpenIddictPermissions.Users.ImpersonateOpenIddict.Users.ImpersonateImpersonate a user
ConstantValueDescription
OpenIddictPermissions.Roles.ReadOpenIddict.Roles.ReadList and view roles
OpenIddictPermissions.Roles.CreateOpenIddict.Roles.CreateCreate new roles
OpenIddictPermissions.Roles.DeleteOpenIddict.Roles.DeleteDelete roles
ConstantValueDescription
OpenIddictPermissions.Groups.ReadOpenIddict.Groups.ReadList and view groups
OpenIddictPermissions.Groups.CreateOpenIddict.Groups.CreateCreate new groups
OpenIddictPermissions.Groups.ManageOpenIddict.Groups.ManageManage group details and membership
OpenIddictPermissions.Groups.DeleteOpenIddict.Groups.DeleteDelete groups
ConstantValueDescription
OpenIddictPermissions.Applications.ReadOpenIddict.Applications.ReadList and view OIDC applications
OpenIddictPermissions.Applications.CreateOpenIddict.Applications.CreateCreate new OIDC applications
OpenIddictPermissions.Applications.ManageOpenIddict.Applications.ManageManage OIDC application details
OpenIddictPermissions.Applications.DeleteOpenIddict.Applications.DeleteDelete OIDC applications
OpenIddictPermissions.Applications.RotateOpenIddict.Applications.RotateRotate client secrets
ConstantValueDescription
OpenIddictPermissions.Scopes.ReadOpenIddict.Scopes.ReadList and view OIDC scopes
OpenIddictPermissions.Scopes.CreateOpenIddict.Scopes.CreateCreate new OIDC scopes
OpenIddictPermissions.Scopes.ManageOpenIddict.Scopes.ManageManage OIDC scope details
OpenIddictPermissions.Scopes.DeleteOpenIddict.Scopes.DeleteDelete OIDC scopes
ConstantValueDescription
OpenIddictPermissions.Authorizations.ReadOpenIddict.Authorizations.ReadList and view OIDC authorizations
OpenIddictPermissions.Authorizations.RevokeOpenIddict.Authorizations.RevokeRevoke OIDC authorizations

Configured by AddGranitOpenIddict():

options.User.RequireUniqueEmail = true;
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
options.SignIn.RequireConfirmedEmail = true;

These are build-time defaults. The MaxLoginAttempts runtime setting (OpenIddict.MaxLoginAttempts) overrides MaxFailedAccessAttempts per-tenant.