# Application deployment checklist Use the items that apply to your integration. For explanations, see [deploy your application](https://www.udibo.com/docs/oauth2/guides/production-deployment). If Udibo hosts sign-in, review your client/BFF/API boundaries; the app-owned identity and issuer sections apply only when you host those flows. ## Configuration and secrets - [ ] Issuer, app origin, and exact callbacks are configured for this environment. - [ ] Production credentials and data are separate from local and preview environments. - [ ] No demo credentials, fallback secrets, or local test-provider endpoints remain. - [ ] Client secrets, cookie keys, and signing keys stay on the backend and out of logs. ## Browser, BFF, and API - [ ] HTTPS cookie and CSRF defaults are enabled; custom browser requests send the CSRF header. - [ ] The BFF's `sessionStore` and `authRequestStorage` work on every instance that serves the app: encrypted-cookie stores with secrets every instance shares, a separate one per store instance and per app, or stores over shared storage. `MemorySessionStore` and `MemoryAuthRequestStorageFactory` appear only in single-process, test and local configurations. If sign-out must revoke a stolen session cookie, use a shared `SessionStore`: `EncryptedCookieSessionStore` keeps a copied cookie valid until its `maxAgeMs`. See [choosing the BFF's stores](https://www.udibo.com/docs/oauth2/guides/production-deployment#choosing-the-bffs-stores). - [ ] Login state and PKCE verifier survive callbacks to a different app instance. - [ ] A server-side `DirectClient` that signs users in or runs the device flow has an `authRequestStorage` (on the client or passed per call) and a `refreshTokenStorage` that every instance can read and that outlives a restart. `MemoryAuthRequestStorage` and `MemoryRefreshTokenStorage` appear only in single-process, test and local configurations. See [DirectClient storage outside a browser](https://www.udibo.com/docs/oauth2/known-limitations#directclient-storage-outside-a-browser). - [ ] Pending sign-ins are bounded. A multi-instance or internet-facing BFF uses `EncryptedCookieAuthRequestStorage`, or shared storage with its own cap. The login route has a rate limit, and `maxReturnToLength` (default 2048) suits your return paths. See [pending sign-in limits](https://www.udibo.com/docs/oauth2/known-limitations#pending-sign-in-limits). - [ ] Behind a TLS-terminating proxy, the app origin comes from configuration (`redirectUri` or `resolveOrigin`), and SSO logout sends the registered `https` post-logout redirect URI. - [ ] Sessions expire consistently and stateful updates reject revoked or missing sessions. - [ ] Local logout, upstream revocation, and optional SSO logout have each been tested. - [ ] Session listings expose non-secret row IDs, never cookie credentials or token material. - [ ] The API validates issuer, token type, applicable audience, and required scopes. - [ ] Record-level authorization runs on the server, independently of React rendering guards. - [ ] The app handles invalid tokens separately from issuer outages. - [ ] Any proxy has a fixed trusted target; trusted-forwarded-header policy matches deployment. - [ ] Every route that reads its own body has a request-size limit in the framework or reverse proxy, mounted ahead of `protect()`. The package caps only its own reads: `maxTokenBodyBytes` for the form-body `access_token` search and `maxBodyBytes` for `honoIdentityRoutes`. ## If your app hosts an authorization server - [ ] PKCE, state, and confidential-client authentication are enabled. - [ ] Registered callbacks and allowed grants are restricted to the app's actual clients. - [ ] Codes and refresh-token rotation claims are consumed atomically. - [ ] The token store implements `rotate`, claiming a refresh token and saving its successor in one step that `revokeFamily` cannot interleave with, and passes `runTokenRotationContractTests` with its barrier wired. - [ ] The token store implements `exchangeCode`, claiming a code and saving its token in one step, and passes `runCodeExchangeContractTests` with its barrier wired; its `revokeCode` revokes nothing for a client other than the code's own, or for a `codeVerifierHash` other than the one saved with the code's tokens. - [ ] Without `rotate`, family revocation, from a replay or from revoking a rotated-out token, cannot be undone by a concurrent token save: `revokeFamily` records the family and `save` stores any later member of it already revoked. - [ ] `getRevokedRefreshToken` returns every tombstone; a replay grace comes from `replayGraceSeconds`, judged on the store's clock by `isWithinReplayGrace` when the store stamps `rotatedAt` itself, not from hiding recent tombstones. - [ ] Client-credentials tokens represent the client or its service account, not its human owner. - [ ] Consent and scope policy match the clients you allow. - [ ] `maxBodyBytes` stays at its 64 KiB default unless your clients send larger token, revocation, introspection or end-session bodies. - [ ] Persisted signing keys survive deployment; rotation and JWT revocation limits are understood. - [ ] The deprecated password grant is not enabled for new integrations. ## If your app hosts login - [ ] The full password credential, including `params`, is persisted. - [ ] Automatic rehash/import uses atomic `replaceCredential`; a failed comparison writes nothing, and the sign-in proceeds only if the password re-verifies against the credential now stored. - [ ] Rate limiting and lockout are explicitly configured and enforced. - [ ] `RateLimiter` and `AccountLockout` use a `RateLimitStore` and a `LockoutStore` that every instance shares, with an atomic `increment`. `MemoryRateLimitStore` and `MemoryLockoutStore` appear only in single-process, test and local configurations. See [rate limit and lockout storage](https://www.udibo.com/docs/oauth2/known-limitations#rate-limit-and-lockout-storage-across-instances). - [ ] Email requests and OTP/MFA attempts are throttled; concurrent resend policy is explicit. - [ ] OTP consumption and recovery-code consumption permit one successful caller. - [ ] Password reset invalidates sessions; optional sign-in-link/OTP cleanup is implemented and monitored. - [ ] Email verification is conditional on the current address matching the address proved. - [ ] MFA enrollment, disable, recovery, and verification routes authenticate and authorize the user. - [ ] A completed first factor creates pending MFA state, not a full application session. - [ ] External identities are keyed by trusted provider and subject; linking requires account proof. - [ ] Apple callbacks accept form POSTs and use the required Secure, SameSite=None transient cookie. ## Verification and maintenance - [ ] Contract suites pass against the actual persistent adapters. - [ ] Tests cover concurrent redemption, callback mismatch, expired/revoked sessions, and insufficient scope. - [ ] Backups, retention, and recovery are exercised without restoring revoked access unintentionally. - [ ] Audit records omit credentials; delivery and persistence failures are observable. - [ ] The [known limitations](https://www.udibo.com/docs/oauth2/known-limitations) have been reviewed for enabled features.