Configuration Reference
Full configuration example
Section titled “Full configuration example”{ "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 } }}GranitOpenIddictOptions
Section titled “GranitOpenIddictOptions”Configuration section: OpenIddict
Bound in: GranitOpenIddictModule.ConfigureServices()
| Property | Type | Default | Description |
|---|---|---|---|
Issuer | Uri? | null | Explicit OIDC issuer URI. When null, the issuer is inferred from the incoming request URL. Set explicitly for multi-node deployments behind a load balancer. |
UseReferenceTokens | bool | false | Issue 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. |
EnableEntityCaching | bool | false | Enable 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. |
RequirePar | bool | false | Require 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. |
EnableTokenExchange | bool | false | Enable 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. |
EnableFapi2Profile | bool | false | Enable 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 }}GranitOpenIddictClientOptions
Section titled “GranitOpenIddictClientOptions”Configuration section: OpenIddict:Client
Bound in: GranitOpenIddictModule.ConfigureServices()
| Property | Type | Default | Description |
|---|---|---|---|
AutoRegisterExternalUsers | bool | true | Auto-create a GranitUser on first login via an external provider. When false, returns 403 if no existing account matches the email. |
Providers | ExternalProviderOptions[] | [] | External login providers to configure. |
ExternalProviderOptions
Section titled “ExternalProviderOptions”| Property | Type | Default | Description |
|---|---|---|---|
Name | string | "" | Provider name: "Google", "Microsoft", or "GitHub". |
ClientId | string | "" | OAuth 2.0 client ID obtained from the provider’s developer console. |
ClientSecret | string | "" | OAuth 2.0 client secret. Use Granit.Vault in production. |
Scopes | string[] | ["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"] } ] } }}GranitOpenIddictSeedingOptions
Section titled “GranitOpenIddictSeedingOptions”Configuration section: OpenIddict:Seeding
Bound in: GranitOpenIddictModule.ConfigureServices() and
GranitOpenIddictEntityFrameworkCoreModule.ConfigureServices()
| Property | Type | Default | Description |
|---|---|---|---|
Applications | OidcApplicationSeedDescriptor[] | [] | OIDC applications to seed at startup. Idempotent upsert based on ClientId. |
Scopes | OidcScopeSeedDescriptor[] | [] | OIDC scopes to seed at startup. Idempotent upsert based on Name. |
OidcApplicationSeedDescriptor
Section titled “OidcApplicationSeedDescriptor”| Property | Type | Description |
|---|---|---|
ClientId | string | Unique client identifier (upsert key). |
ClientSecret | string? | Client secret. null for public clients (SPAs). Encrypted before persistence. |
DisplayName | string | Human-readable display name. |
Permissions | string[] | OpenIddict permissions (e.g., ept:token, gt:authorization_code, scp:openid). |
RedirectUris | string[] | Allowed redirect URIs after authorization. |
PostLogoutRedirectUris | string[] | Allowed redirect URIs after logout. |
SigningKeyJwk | string? | JWK Set containing the client’s public key for private_key_jwt authentication (RFC 7523). |
OidcScopeSeedDescriptor
Section titled “OidcScopeSeedDescriptor”| Property | Type | Description |
|---|---|---|
Name | string | Unique scope name (upsert key). |
DisplayName | string | Human-readable display name. |
Resources | string[] | Resources associated with this scope (audience values). |
OpenIddict permission reference
Section titled “OpenIddict permission reference”| Prefix | Meaning | Examples |
|---|---|---|
ept: | Endpoint | ept:authorization, ept:token, ept:logout, ept:introspection, ept:revocation, ept:device |
gt: | Grant type | gt:authorization_code, gt:client_credentials, gt:refresh_token, gt:urn:ietf:params:oauth:grant-type:device_code |
rst: | Response type | rst:code, rst:id_token, rst:token |
scp: | Scope | scp: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": []}GranitPasskeyOptions
Section titled “GranitPasskeyOptions”Configuration section: OpenIddict:Passkeys
Bound in: GranitOpenIddictModule.ConfigureServices() and
GranitOpenIddictEntityFrameworkCoreModule.ConfigureServices()
| Property | Type | Default | Description |
|---|---|---|---|
ServerDomain | string | "" | WebAuthn Relying Party ID (domain). Required when passkeys are enabled. Must match the domain where the application is hosted (e.g., "example.com"). |
AuthenticatorTimeout | TimeSpan | 00:05:00 | Timeout for authenticator operations (registration and assertion ceremonies). |
ChallengeSize | int | 32 | Challenge size in bytes for WebAuthn operations. |
Example:
{ "OpenIddict": { "Passkeys": { "ServerDomain": "example.com", "AuthenticatorTimeout": "00:05:00", "ChallengeSize": 32 } }}GranitKeyRotationOptions
Section titled “GranitKeyRotationOptions”Bound from: OpenIddict:KeyRotation section
| Property | Type | Default | Description |
|---|---|---|---|
Enabled | bool | false | Enable automatic key rotation. When disabled, ephemeral keys are used. |
KeyLifetime | TimeSpan | 90 days | How long a signing key remains active before rotation. |
GracePeriod | TimeSpan | 14 days | How long a retired key remains in JWKS for token verification. Should be >= max token lifetime. |
RotationLeadTime | TimeSpan | 7 days | How far in advance a new key is generated before the active key expires. |
RsaKeySize | int | 2048 | RSA key size in bits. Use 4096 for higher security requirements. |
SigningAlgorithm | string | RS256 | The 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" } }}OpenIddictEndpointsOptions
Section titled “OpenIddictEndpointsOptions”Configured in: MapOpenIddictEndpoints() lambda
| Property | Type | Default | Description |
|---|---|---|---|
AccountRoutePrefix | string | "api/account" | Route prefix for account self-service endpoints. |
AdminRoutePrefix | string | "api/admin" | Route prefix for admin management endpoints. |
AccountTagName | string | "Account" | OpenAPI tag for account endpoints. |
AdminTagName | string | "Administration" | OpenAPI tag for admin endpoints. |
Example:
app.MapOpenIddictEndpoints(options =>{ options.AccountRoutePrefix = "api/v1/account"; options.AdminRoutePrefix = "api/v1/admin";});GranitOpenIddictDbProperties
Section titled “GranitOpenIddictDbProperties”Static properties for table naming. Must be set before ConfigureServices
completes — EF Core caches the compiled model after first use.
| Property | Type | Default | Description |
|---|---|---|---|
DbTablePrefix | string | "openiddict_" | Table name prefix for all Identity and OpenIddict tables. |
DbSchema | string? | null | Database schema. null uses the provider’s default schema. |
Example:
// Before builder.Build()GranitOpenIddictDbProperties.DbTablePrefix = "auth_";GranitOpenIddictDbProperties.DbSchema = "identity";Per-tenant settings (Granit.Settings)
Section titled “Per-tenant settings (Granit.Settings)”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 key | Type | Default | Description |
|---|---|---|---|
OpenIddict.AccessTokenLifetime | TimeSpan | 01:00:00 (1 hour) | Access token lifetime. |
OpenIddict.RefreshTokenLifetime | TimeSpan | 14.00:00:00 (14 days) | Refresh token lifetime. |
OpenIddict.AuthCodeLifetime | TimeSpan | 00:05:00 (5 minutes) | Authorization code lifetime. |
OpenIddict.MaxLoginAttempts | int | 5 | Maximum failed login attempts before account lockout. |
OpenIddict.IdleSessionTimeout | int | 0 (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 (Granit.Features)
Section titled “Feature flags (Granit.Features)”Feature flags are registered via OpenIddictFeatureDefinitionProvider (auto-discovered
by GranitFeaturesModule). Resolution order: Tenant > Plan > Default.
| Feature key | Default | Description |
|---|---|---|
OpenIddict.TwoFactor | true | TOTP-based two-factor authentication. |
OpenIddict.DeviceFlow | false | OAuth 2.0 Device Authorization Grant (RFC 8628). |
OpenIddict.ExternalLogins | true | External login providers (Google, Microsoft, GitHub). |
OpenIddict.PkceRequired | true | PKCE requirement for all authorization code flows. |
OpenIddict.Passkeys | false | WebAuthn/FIDO2 passwordless authentication. |
OpenIddict.JarRequired | false | Require 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";}Permissions
Section titled “Permissions”All 23 permission constants are defined in OpenIddictPermissions and follow the
[Group].[Resource].[Action] convention. They are registered via
OpenIddictPermissionDefinitionProvider (auto-discovered by GranitAuthorizationModule).
| Constant | Value | Description |
|---|---|---|
OpenIddictPermissions.Users.Read | OpenIddict.Users.Read | List and view users |
OpenIddictPermissions.Users.Create | OpenIddict.Users.Create | Create new users |
OpenIddictPermissions.Users.Manage | OpenIddict.Users.Manage | Update user details |
OpenIddictPermissions.Users.Delete | OpenIddict.Users.Delete | Soft-delete users |
OpenIddictPermissions.Users.Impersonate | OpenIddict.Users.Impersonate | Impersonate a user |
| Constant | Value | Description |
|---|---|---|
OpenIddictPermissions.Roles.Read | OpenIddict.Roles.Read | List and view roles |
OpenIddictPermissions.Roles.Create | OpenIddict.Roles.Create | Create new roles |
OpenIddictPermissions.Roles.Delete | OpenIddict.Roles.Delete | Delete roles |
Groups
Section titled “Groups”| Constant | Value | Description |
|---|---|---|
OpenIddictPermissions.Groups.Read | OpenIddict.Groups.Read | List and view groups |
OpenIddictPermissions.Groups.Create | OpenIddict.Groups.Create | Create new groups |
OpenIddictPermissions.Groups.Manage | OpenIddict.Groups.Manage | Manage group details and membership |
OpenIddictPermissions.Groups.Delete | OpenIddict.Groups.Delete | Delete groups |
Applications
Section titled “Applications”| Constant | Value | Description |
|---|---|---|
OpenIddictPermissions.Applications.Read | OpenIddict.Applications.Read | List and view OIDC applications |
OpenIddictPermissions.Applications.Create | OpenIddict.Applications.Create | Create new OIDC applications |
OpenIddictPermissions.Applications.Manage | OpenIddict.Applications.Manage | Manage OIDC application details |
OpenIddictPermissions.Applications.Delete | OpenIddict.Applications.Delete | Delete OIDC applications |
OpenIddictPermissions.Applications.Rotate | OpenIddict.Applications.Rotate | Rotate client secrets |
Scopes
Section titled “Scopes”| Constant | Value | Description |
|---|---|---|
OpenIddictPermissions.Scopes.Read | OpenIddict.Scopes.Read | List and view OIDC scopes |
OpenIddictPermissions.Scopes.Create | OpenIddict.Scopes.Create | Create new OIDC scopes |
OpenIddictPermissions.Scopes.Manage | OpenIddict.Scopes.Manage | Manage OIDC scope details |
OpenIddictPermissions.Scopes.Delete | OpenIddict.Scopes.Delete | Delete OIDC scopes |
Authorizations
Section titled “Authorizations”| Constant | Value | Description |
|---|---|---|
OpenIddictPermissions.Authorizations.Read | OpenIddict.Authorizations.Read | List and view OIDC authorizations |
OpenIddictPermissions.Authorizations.Revoke | OpenIddict.Authorizations.Revoke | Revoke OIDC authorizations |
ASP.NET Core Identity defaults
Section titled “ASP.NET Core Identity defaults”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.