Skip to content

Options reference

Every public option accepted by op.New, grouped by what it touches. The first four are constructor-required; everything else is optional and refines the defaults.

How to read this page

Click the option name for the deep-dive page. The "Section" column tells you which discovery / endpoint surface the option moves. "Default" is empty when the option has no built-in default — supplying it is the only way to enable the behaviour.

What option do I need?

This page is a flat reference of the public op.New options. With 70+ options the table can be hard to scan when you arrive with a specific goal in mind. Use the decision tree below to find the relevant area, then jump into the matching section of the table.

Decision tree routing a configuration goal — fresh OP, FAPI switch, single feature, grant restriction, sender-constraint, or token format — to the op.New option that handles it, falling through to the full table.Booting a fresh OP?Required optionsYesNoEnable FAPI 2.0 in one switch?WithProfile(...)YesNoJust one feature, no profile?WithFeature(...)YesNoRestrict grants at /token?WithGrants(...)YesNoSender-constrained access tokens?WithFeature(DPoP|MTLS)YesNoJWT vs opaque access tokens?WithAccessTokenFormat(...)YesNoNone match — browse the full option table below by section.
  • You're booting a fresh OP for the first time → start with WithIssuer, WithStore, WithKeyset, and usually WithCookieKeys. WithCookieKeys is required when authorization_code is enabled, which is the default grant set. See Required options and the minimal OP walkthrough.
  • You want to declare OAuth 2.1 posture without adopting FAPIWithProfile(profile.Baseline) requires PKCE on every authorization-code request and otherwise keeps the OIDC Core defaults. For FAPI 2.0, use profile.FAPI2Baseline (or profile.FAPI2MessageSigning, profile.FAPICIBA); these profiles auto-select DPoP unless you explicitly enable mTLS. A profile that needs a grant you did not wire fails op.New rather than mounting the endpoint for you — profile.FAPICIBA requires grant.CIBA. See Declaring a security profile, Use case: FAPI 2.0 Baseline and Concepts: FAPI.
  • You want a single feature without committing to a profileWithFeature(feature.PAR) / JAR / JARM / DPoP / MTLS / Introspect / Revoke. Public and native clients always require PKCE; FAPI profiles require it for every authorization-code client. Dynamic Registration, RAR, and Grant Management are enabled through their dedicated options because they need extra configuration.
  • You want to restrict the grant types accepted at /tokenWithGrants(grant.AuthorizationCode, grant.RefreshToken, grant.ClientCredentials, grant.DeviceCode, grant.CIBA). The convenience options WithDeviceCodeGrant(), WithCIBA(...), WithCustomGrant(...), and RegisterTokenExchange(...) mount the additional endpoints those grants need.
  • You want sender-constrained access tokens → DPoP path: WithFeature(feature.DPoP) plus optional WithDPoPNonceSource(op.NewInMemoryDPoPNonceSource(...)). mTLS path: WithFeature(feature.MTLS) plus optional WithMTLSProxy(headerName, trustedCIDRs). See Concepts: sender-constrained tokens, DPoP, mTLS, and Use case: DPoP nonce.
  • You want JWT versus opaque access tokensWithAccessTokenFormat(...) for the OP-wide default and WithAccessTokenFormatPerAudience(...) for RFC 8707 resource-scoped overrides. See Concepts: access-token format.
  • You want pairwise sub per sectorWithPairwiseSubject(salt) (32-byte salt minimum). See Use case: pairwise subject.
  • You want to seed clients statically at bootWithStaticClients(op.PublicClient(...), op.ConfidentialClient(...), op.PrivateKeyJWTClient(...)). See Concepts: client types.
  • You want Dynamic Client RegistrationWithDynamicRegistration(...). See Use case: Dynamic Client Registration.
  • You want token introspection or revocation endpointsWithFeature(feature.Introspect) and / or WithFeature(feature.Revoke). The "Profile, features, grants" table below covers fine-tuning.
  • You want to extend the scope catalogWithScope(op.PublicScope("name", "label")) for OIDC-discovery-visible scopes, WithScope(op.InternalScope("name")) for internal-only ones. See Concepts: scopes and claims and Use case: scopes.
  • You want a custom grant_typeWithCustomGrant(handler). See Use case: custom grant.
  • You want internationalization (i18n)WithDefaultLocale(...), WithLocale(bundle), WithPreferredLocaleStore(...). See Use case: i18n.
  • You want JWE encryption of id_token / userinfo / JARM / introspectionWithEncryptionKeyset(...) and optionally WithSupportedEncryptionAlgs(algs, encs) to narrow the default allow-list. See Use case: JWE encryption.
  • You want CORS for SPA clientsWithCORSOrigins(...). See Use case: CORS for SPA.
  • You want Prometheus metricsWithPrometheus(registry). The library does not mount /metrics; expose the registry from your own router. See Use case: Prometheus metrics.
  • You want audit logging on a separate sink from app logsWithAuditLogger(*slog.Logger). See Audit event catalog.
  • You want to swap the entire interaction surface for a SPAWithInteractionDriver(interaction.Driver). See Use case: SPA custom interaction.

Required and conditionally required

OptionValueSectionDefault
WithIssuerstringdiscovery issuer, JWT iss, cookie scope
WithStorestore.Storeevery protocol-state substore
WithUserStorestore.UserStorereads ID Token and /userinfo claims from an application-owned user store without wrapping the WithStore backendWithStore(...).Users()
WithKeysetop.Keyset (P-256 / ES256)JWKS, JWS signing
WithCookieKeys32-byte key(s)session / CSRF cookie AES-256-GCMrequired when authorization_code is enabled

Profile, features, grants

OptionValueSectionDefault
WithProfileprofile.Profiledeclares profile.Baseline (OAuth 2.1: PKCE on every authorization-code request) or a FAPI profile. FAPI profiles select DPoP when they require DPoP-or-mTLS and mTLS was not explicitly enabled. Missing features a profile requires are switched on for you; a missing grant fails op.New instead, with the error naming the option that activates it.none
WithFeaturefeature.Flag (one per call; repeatable)enables PAR / DPoP / mTLS / JAR / JARM / introspect / revoke individuallyconservative defaults
WithGrants...grant.Type (variadic)restricts the grant types accepted at /token; may be called at most once, so compose the full set before passing options to op.Newauthorization_code, refresh_token
WithScopeop.Scope (one per call; use the op.PublicScope / op.InternalScope constructors)extends the scope catalogopenid, profile, email, address, phone, offline_access
WithOpenIDScopeOptional(no args)makes pure OAuth 2.0 (scope without openid) acceptableopenid required
WithStrictOfflineAccess(no args)gates refresh_token issuance behind explicit offline_access consentlax (refresh on any openid grant)

Clients & registration

OptionValueSectionDefault
WithStaticClients...op.ClientSeed (use op.PublicClient / op.ConfidentialClient / op.PrivateKeyJWTClient)seeds the client registry at bootempty
WithFirstPartyClients...string (client IDs)grants first-party consent skipnone
WithDynamicRegistrationop.RegistrationOptionmounts /register (RFC 7591/7592)disabled

Authentication & login flow

OptionValueSectionDefault
WithLoginFlowop.LoginFlowdeclarative DAG of Step + Rule (recommended)none
WithAuthenticators...op.Authenticator (variadic)low-level seam (mutually exclusive with WithLoginFlow)none
WithInteractionDriverinteraction.Driverswaps the entire interaction transport (HTML driver / SPA driver / custom)bundled HTML driver
WithInteractions...op.Interaction (variadic)non-credential prompts (T&C, KYC) layered on top of the driverconsent only
WithCaptchaVerifierop.CaptchaVerifierupstream captcha provider for StepCaptchanone
WithRiskAssessorop.RiskAssessorfeeds RuleRisk and LoginContext.RiskScorenone
WithLoginAttemptObserverop.LoginAttemptObservercounts failed attempts for RuleAfterFailedAttemptsnone
WithMFAEncryptionKeys32-byte key(s)AES-256-GCM seal of TOTP secrets at restnone
WithAuthnLockoutStorestore.AuthnLockoutStorepersists per-subject failed-attempt counters consulted by RuleAfterFailedAttemptsnone
WithACRPolicyop.ACRPolicy (interface)step-up acr/aal mappingidentity

Leaving WithAuthnLockoutStore unset disables cross-factor tracking, so only the built-in per-factor TOTP / email-OTP counters apply. Set it to activate cross-factor tracking for the built-in possession / recovery factors (StepTOTP, StepEmailOTP, StepRecoveryCode). It does not automatically wrap primary password / passkey authentication or ExternalStep custom factors; those remain owned by the embedder's user store or custom authenticator. The SQL and DynamoDB adapters both expose durable stores through AuthnLockouts(); inmem.Store.AuthnLockouts() is process-local and resets on restart.

Authentication-factor records are intentionally outside store.Store. StepTOTP, PrimaryPasskey, StepRecoveryCode, and StepEmailOTP receive their own stores because enrollment schema, encryption keys, and account-recovery policy belong to the embedding application. In-memory, SQL, and DynamoDB adapters expose the matching accessors. examples/27-durable-mfa-store uses the shipped SQL adapter's factor stores alongside the core OP tables; implement the factor-store contracts yourself only for another backend.

Two factor-store contracts matter for durability-sensitive deployments. store.EmailOTPStore.Get must keep records readable until EmailOTPRecord.RetainUntil, not merely until the code's ExpiresAt, so resend caps and brute-force counters survive an expired code. store.RecoveryStore.Consume must compare the presented code hash with the currently stored slot and reject stale hashes, so regenerated recovery batches revoke old leaked codes instead of burning a slot in the new batch.

UI

OptionValueSectionDefault
WithSPAUIop.SPAUI (struct: LoginMount / ConsentMount / LogoutMount / StaticDir)mounts the SPA shell and static asset tree while the OP serves the JSON interaction state surfaceoff
WithConsentUIop.ConsentUI (wraps a *html/template.Template)renders consent with an embedder-supplied HTML template; OP still owns state, CSRF, and persistencebundled template
WithChooserUIop.ChooserUI (wraps a *html/template.Template)renders prompt=select_account with an embedder-supplied HTML templatebundled template
WithCORSOrigins...stringstrict-CORS allowlist (auto-derived from redirect URIs if omitted)derived
WithDefaultLocaleop.Locale (BCP 47 tag)default UI locale when the request carries no ui_locales"en"
WithLocaleop.LocaleBundle (one per call; repeatable)registers a per-locale message bundle for the bundled HTML driverEnglish + Japanese seed
WithPreferredLocaleStoreop.PreferredLocaleStoreper-user locale override consulted at the head of the §L.2 chainnone

WithSPAUI is mutually exclusive with WithConsentUI: both own the consent rendering surface. WithChooserUI may be configured alongside WithSPAUI, but SPA mode owns the chooser through the JSON state envelope; the chooser template is ignored and op.New emits a structured warning. See Custom chooser UI.

Tokens

OptionValueSectionDefault
WithAccessTokenFormatop.AccessTokenFormat (AccessTokenFormatJWT / AccessTokenFormatOpaque)JWT vs opaque, OP-wideJWT
WithAccessTokenFormatPerAudiencemap[string]op.AccessTokenFormat (RFC 8707 resource → format)mixed format by audienceOP-wide value
WithAccessTokenRevocationStrategyop.AccessTokenRevocationStrategy (RevocationStrategyGrantTombstone / RevocationStrategyJTIRegistry / RevocationStrategyNone)revocation policy for issued JWT access tokens; GrantTombstone (default) needs Store.GrantRevocations(), JTIRegistry needs Store.AccessTokens() — both checked at op.Newgrant tombstone
WithAccessTokenTTLtime.Durationaccess token lifetime5 min
WithRefreshTokenTTLtime.Durationrefresh token lifetime (non-offline)30 days
WithRefreshTokenOfflineTTLtime.Durationrefresh token lifetime when offline_access grantedinherits WithRefreshTokenTTL (zero value defers)
WithRefreshGracePeriodtime.Duration (zero disables; negative rejected)rotation grace window60 s
WithDPoPNonceSourceop.DPoPNonceSource (interface)server-supplied DPoP nonce store (op.NewInMemoryDPoPNonceSource provides one)none

WithInMemoryDPoPNonceLogger is a helper option for op.NewInMemoryDPoPNonceSource, not an op.New option. Use it only when you use the bundled in-memory nonce source.

Discovery & endpoints

OptionValueSectionDefault
WithEndpointsop.Endpoints (struct: per-endpoint path overrides)overrides default endpoint pathsspec defaults
WithMountPrefixstring (must start with /; pass / for root)embeds an issuer-relative path prefix/oidc
WithClaimsSupported...string (variadic)populates claims_supported in discoveryomitted
WithClaimsParameterSupportedbooltoggles claims_parameter_supported; false also makes authorize / PAR ignore claims payloads after malformed JSON has been rejectedtrue
WithACRValuesSupported...string (variadic)publishes acr_values_supported; FAPI / eIDAS / NIST 800-63 deployments use this to advertise honored ACR valuesempty (omitted from discovery)
WithDiscoveryMetadataop.DiscoveryMetadata (typed service_documentation, policy / TOS / UI locale / mTLS alias fields plus Extra map[string]any)injects RFC 8414 / OIDC Discovery metadata not owned by the OP; UILocalesSupported overrides the auto-derived locale list when non-empty, and Extra keys that collide with OP-controlled fields are rejectednone
WithPARLifetimetime.Durationoverrides the lifetime of request_uri values issued by /par; expiry is checked when the browser presents the URI at /authorize, while later code emission remains single-use60 s
WithJWKSRotationActivefunc() boolpredicate that flips JWKS Cache-Control to short-cache during a rotation windowalways long-cache

Subject strategy

OptionValueSectionDefault
WithSubjectGeneratorop.SubjectGenerator (interface)overrides the sub claim derivation; the in-tree op/subject.UUIDv7 is the defaultUUIDv7 passthrough
WithPairwiseSubject[]byte salt (≥ 32 bytes)enables OIDC Core §8.1 pairwise sub derivation per sector; mid-life switching is rejected at op.Newpublic (UUIDv7)

See Use case: pairwise subject.

Grants — Device Code, CIBA, Custom, Token Exchange

OptionValueSectionDefault
WithDeviceCodeGrant(no args)enables the RFC 8628 device-authorization grant; mounts /device_authorization and registers the URN at /tokendisabled
WithDeviceVerificationURIstring (absolute URL)overrides the verification URI advertised on the device's display (default <issuer>/device)derived
WithDeviceCodeExpirytime.Durationoverrides the expires_in lifetime for newly issued device_code records; independent of the access-token TTL10 min
WithDeviceCodePollIntervaltime.Durationoverrides the advertised polling interval; clients polling faster receive slow_down5 s
WithCIBA...op.CIBAOptionenables CIBA poll mode; mounts /bc-authorize and registers the CIBA URN. Sub-options: WithCIBAHintResolver (required), WithCIBADefaultExpiresIn, WithCIBAMaxExpiresIn, WithCIBAPollInterval, WithCIBAMaxPollViolationsdisabled
WithCustomGrantop.CustomGrantHandlerregisters an embedder-defined grant_type URN at /token; the handler returns a verbatim access token or a BoundAccessToken request the OP signsnone
RegisterTokenExchangeop.TokenExchangePolicyenables the RFC 8693 token-exchange grant; the policy decides admission per request and may narrow OP-computed defaultsdisabled

WithDeviceCodeExpiry and WithDeviceCodePollInterval are intentionally not derived from WithAccessTokenTTL; short-lived access tokens should not make a TV / CLI pairing ceremony expire before the user can reach the second screen. See Use case: device code, CIBA, Custom grant, Token exchange.

Authorization features — RAR, Grant Management, Protected Resource Metadata

OptionValueSectionDefault
WithAuthorizationDetailTypes...op.AuthorizationDetailTypeenables RFC 9396 Rich Authorization Requests; registers each accepted type with its validator. authorization_details is then validated at /authorize, /par, /token, persisted on the grant, echoed on JWT access tokens and introspection, and advertised in discovery. A nil Validate is rejected at op.Newdisabled
WithGrantManagement(actions []op.GrantManagementAction, actionRequired bool)enables the OAuth 2.0 Grant Management draft; honours grant_management_action / grant_id, mounts the query / revoke endpoint, stamps grant_id on the token response, and advertises the configured action set in discovery. Experimental (tracks an IETF draft)disabled
WithProtectedResources...op.ProtectedResourcepublishes RFC 9728 protected-resource metadata at /.well-known/oauth-protected-resource plus each resource path suffix, with the issuer in authorization_serversnone

op.StepUpChallenge(realm, acrValues, maxAge) is a standalone helper (not an op.New option) that builds the RFC 9470 WWW-Authenticate: Bearer challenge an embedder's resource server returns; the OP itself never emits it.

See Rich authorization requests, Grant management, Protected resource metadata, MFA / step-up.

Encryption (JWE)

OptionValueSectionDefault
WithEncryptionKeysetop.EncryptionKeyset (RSA ≥ 2048 / EC P-256/384/521 private keys, use=enc)publishes encryption JWKs; required for inbound JWE request objects and outbound JWE responses (id_token / userinfo / JARM / introspection)none
WithSupportedEncryptionAlgs(algs []string, encs []string)narrows the default allow-list (RSA-OAEP-256 / ECDH-ES{,+A128KW,+A256KW} × A{128,256}GCM); cannot extend itfull allow-list

See Use case: JWE encryption.

mTLS / proxy / network

OptionValueSectionDefault
WithMTLSProxy(headerName string, trustedCIDRs []string)header-based mTLS termination at edgenone
WithTrustedProxies...string (CIDRs)resolves X-Forwarded-* / Forwarded to real client IPnone
WithTrustedProxyHosts...string (hostnames)extends the X-Forwarded-Host allowlist beyond the canonical issuer host when trusted proxy CIDRs are configuredissuer host only
WithAllowLocalhostLoopback(no args)admits textual localhost in the RFC 8252 loopback carve-out for dev / native-app demos, and in the issuer itself; literal 127.0.0.1 / [::1] remain the strict defaultsstrict literal loopback only
WithAllowPrivateNetworkJWKS(no args)permits client JWKS hosted on RFC 1918 (test only)denied
WithAllowPrivateNetworkJAR(no args)permits request_uri hosted on RFC 1918 (test only)denied
WithAllowPrivateNetworkSector(no args)permits sector_identifier_uri hosted on RFC 1918 during dynamic registration (test / private RP networks only)denied
WithJWKSHTTPTransporthttp.RoundTrippercustom transport for RP-controlled JWKS fetches used by JAR and private_key_jwt, while preserving the dial-time SSRF gatesystem-trust transport
WithBackchannelAllowPrivateNetworkboolpermits backchannel_logout_uri on RFC 1918 (test only)false
WithAllowInsecureBackchannelLogoutForDev(no args)admits plain-HTTP loopback backchannel_logout_uri values and delivery only for dev / CI fixturesdenied
WithBackchannelLogoutHTTPClient*http.ClientHTTP client for back-channel logout fan-outdefault
WithBackchannelLogoutTimeouttime.Durationper-RP fan-out timeout5 s

Observability

OptionValueSectionDefault
WithLogger*slog.Loggerstructured operational log sink (handler is wrapped with the redaction middleware)discard
WithAuditLogger*slog.Loggerdedicated audit-event log sinkinherits WithLogger
WithPrometheus*prometheus.Registryregisters OP counters on caller's registry (no /metrics mounted)none

Operational posture

OptionValueSectionDefault
WithSessionDurabilityPostureop.SessionDurabilityPostureannotates back-channel logout audit events for SOCvolatile
WithClockop.Clocktime source (test injection)time.Now

What you do not configure here

These are deliberate non-options — see the linked design rationale for why each is fixed:

  • JOSE verification allow-list — incoming client assertions, JAR request objects, and DPoP proofs use the fixed RS256 / PS256 / ES256 / EdDSA verification set. OP-issued JWTs are signed with ES256 only. No flag widens either surface. See Security posture §2.
  • PKCE methodS256 only. plain is structurally rejected.
  • Cookie scheme__Host- prefix, AES-256-GCM, double-submit CSRF always on. See Required options §WithCookieKeys.
  • Random sourcecrypto/rand only; math/rand is forbidden by lint.
  • /metrics mounting — your router's job, not the library's. See Use case: Prometheus metrics.

Verifying this list

The catalog is grepped from the live source. To audit:

sh
git clone https://github.com/libraz/go-oidc-provider.git
cd go-oidc-provider
grep -rhE '^func With[A-Z]|^func RegisterTokenExchange' \
  op/options.go op/options_authn.go op/options_clients.go \
  op/options_ciba.go op/options_customgrant.go op/options_devicecode.go \
  op/options_discovery.go op/options_encryption.go op/options_features.go \
  op/options_fapi_proxy.go op/options_protocol.go op/options_session.go \
  op/options_subject.go op/access_token_revocation.go op/i18n.go \
  op/registration.go op/authorization_details.go op/grant_management.go \
  op/protected_resource.go \
  | sort -u

The shape (function name + receiver + first parameter type) is the canonical reference; the godoc on each function is the authoritative contract.