Use cases
Each page below pairs with a runnable example under examples/ in the source repo. Examples build behind the example build tag, so they stay out of go test ./... and out of your go.sum:
(cd examples/01-minimal && GOWORK=off go run -tags example .)Most pages open with the problem the feature solves, then say when it earns its complexity and when a simpler built-in path is enough.
If you are new to the library, start with Minimal OP and RP pair, then Comprehensive bundle, and only jump to the pages below when your deployment has that specific need. To pick a page by what you want to build rather than by topic, use Start here.
The reference application
Each numbered example isolates one option in 200–500 lines. sample/ is the other thing: the arc those examples skip, where an account has to come into existence before it can be used. It runs on MySQL plus Redis joined by op/storeadapter/composite, under one docker compose up, and covers:
- signup owned by the application: account creation itself stays with the application, which plugs into the library's registration seam (
LoginFlow.Registrationandprompt=create) - Argon2id password storage
- login and consent through an
interaction.Driverthe application implements itself - TOTP enrolment from an account settings page
- a relying party completing the round-trip
docker compose -f sample/compose.yaml up -d --buildThe Compose file publishes the OP and RP only on 127.0.0.1. The sample protects application-owned POST routes with a double-submit CSRF token and an Origin check; password changes and TOTP enrolment confirmation also require the current password, verified with op.VerifyPassword. These protections belong to the application, outside the OP's interaction endpoint.
Its consent page is a worked example of granular per-scope consent, which the bundled HTML driver deliberately does not offer. Treat it as a demonstration rather than a template: the schema is one embedder's model, signing and cookie keys are regenerated on every start, and it is not built to be hosted.
Index
Every example folder maps to one of the use-case pages below.
Bootstrap & wiring
| Use case | Example | Page |
|---|---|---|
| Smallest possible OP | 01-minimal | Minimal OP and RP pair |
| Comprehensive bundle (every option a typical embedder uses) | 02-bundle | Comprehensive bundle |
Profile & flow
| Use case | Example | Page |
|---|---|---|
| Declare OAuth 2.1 or legacy OIDC posture | 00-security-profile | Declaring a security profile |
| Plain OAuth 2.0 alongside OIDC | 04-oauth2-only | OAuth 2.0 (no openid) |
| FAPI 2.0 Baseline (library PAR + JAR + DPoP default) | 03-fapi2 | FAPI 2.0 Baseline |
| FAPI 2.0 Message Signing (signed requests, JARM, signed introspection, DPoP nonce source) | 54-fapi2-message-signing, and 51-dpop-nonce for the nonce handshake | FAPI 2.0 Message Signing |
FAPI 2.0 with certificate-bound tokens behind a TLS-terminating proxy (WithMTLSProxy + WithTrustedProxies) | 55-mtls-proxy | FAPI 2.0 Baseline |
Native app: public client, PKCE, loopback 127.0.0.1 redirect | 38-native-app | Choose a configuration |
| Service-to-service tokens | 05-client-credentials | client_credentials |
| MCP clients that identify themselves by an HTTPS URL, with no pre-registration | none | MCP authorization server |
| DPoP server nonce flow | 51-dpop-nonce | DPoP nonce flow |
Protect an API with the OP's tokens (op/rs), mounted route by route | 36-resource-server | Protect an API |
| Publish protected resource metadata (RFC 9728) for the APIs an OP fronts | none | Protected resource metadata |
UI
| Use case | Example | Page |
|---|---|---|
| Built-in HTML login, consent, and chooser | 19-default-ui | Choosing a UI path |
| Drive UI from a SPA | 16-custom-interaction, 10-react-login, 17-spa-composite-store | SPA / custom interaction |
| Custom HTML sign-in page | 37-custom-login-ui | Custom login UI |
| Custom HTML consent page | 11-custom-consent-ui | Custom consent UI |
| Custom HTML account chooser | 12-custom-chooser-ui | Custom chooser UI |
Multi-account chooser (prompt=select_account) | 13-multi-account | Multi-account chooser |
| Cross-origin SPA (CORS) | 14-cors-spa | CORS for SPA |
| Locale negotiation | 15-i18n-locale | i18n / locale |
Storage
| Use case | Example | Page |
|---|---|---|
| Persist on a real database | 06-sql-store, 07-mysql-store | Persistent storage (SQL) |
| Persist on DynamoDB | 18-dynamodb-store | DynamoDB storage |
| Rename SQL adapter tables | 25-byo-table-names | Persistent storage (SQL) § Renaming the tables |
| Implement a store from scratch | 26-byo-store-from-scratch | Bring your own store backend |
| Hot/cold split (Redis volatile) | 08-composite-hot-cold, 09-redis-volatile | Hot/cold + Redis |
| Choose between SQL, DynamoDB, Redis hot/cold and a custom store | none | Choosing a storage layout |
Scopes & claims
| Use case | Example | Page |
|---|---|---|
| Public / internal scope split | 60-scopes-public-private | Public / internal scopes |
| OIDC §5.5 claims request parameter | 61-claims-request | Claims request |
| Rich authorization requests (RFC 9396) | none | Rich authorization requests |
Authentication
| Use case | Example | Page |
|---|---|---|
| MFA, captcha, step-up | 20-mfa-totp, 21-risk-based-mfa, 22-login-captcha, 23-step-up | MFA / step-up |
| Durable MFA factor stores on the core database | 27-durable-mfa-store | MFA / step-up |
| Email OTP or recovery codes | 28-email-otp-recovery | MFA / step-up |
| Sign in with a passkey instead of a password | 29-passkey | Passwordless passkey |
| Bring your own user store | 24-byo-userstore | Bring your own user store |
| Migrate bcrypt password hashes to argon2id on login | 53-production-sql | Migrating bcrypt passwords |
An account page that requires a recent sign-in (max_age, rs.RequireMaxAge) | none | Account page |
Advanced grants
| Use case | Example | Page |
|---|---|---|
| Custom grant_type URN | 30-custom-grant | Custom Grant |
| Device code (RFC 8628) | 31-device-code-cli | Device Code |
| CIBA poll mode | 32-ciba-pos | CIBA |
| Token Exchange (RFC 8693) | 33-token-exchange-delegation | Token Exchange |
| Exchange a trusted partner's signed assertion for an access token (RFC 7523) | none | JWT bearer grant |
| Identity chaining across organisations: issue or redeem an ID-JAG (experimental) | none | ID-JAG |
| Long-lived grants the client can query, merge and revoke by id | none | Grant management |
Crypto & subjects
| Use case | Example | Page |
|---|---|---|
| Pairwise subject (OIDC Core §8.1) | 34-pairwise-saas | Pairwise subject |
| Encrypted id_token (JWE) | 35-encrypted-id-token | JWE encryption |
Governance
| Use case | Example | Page |
|---|---|---|
| First-party consent skip | 40-first-party-skip-consent | First-party consent skip |
| Dynamic Client Registration (RFC 7591) | 41-dynamic-registration | Dynamic Client Registration |
| Back-Channel Logout 1.0 | 42-back-channel-logout | Back-Channel Logout |
| Register, update and remove RPs: static seeds and code seams | 53-production-sql | Client onboarding patterns |
Operations
| Use case | Example | Page |
|---|---|---|
| Prometheus metrics | 52-prometheus-metrics | Prometheus metrics |
| FAPI TLS policy and public-JWKS loading | 50-fapi-tls-jwks | FAPI 2.0 Baseline |
Numeric inventory
The example folders are grouped by topic, not by the order they were written:
| Band | Topic |
|---|---|
| 00–09 | bootstrap, core flows, profiles, storage adapters |
| 10–19 | UI and browser integration (SPA, consent, chooser, CORS, i18n) |
| 20–29 | MFA, authentication rules, and user-store projection |
| 30–39 | advanced grants, subject modes, encrypted tokens, federation, resource servers; 37 holds the UI overflow |
| 40–49 | governance: first-party, DCR, back-channel logout |
| 50–59 | operations: FAPI helpers, metrics, tracing, DPoP nonce |
| 60–69 | scopes, claims, and compliance-adjacent examples |
The README in the source repo is the authoritative inventory.