Skip to content

fix(identity): sys_verification.value must not be UNIQUE — breaks OIDC authorize (503)#2333

Merged
os-zhuang merged 1 commit into
mainfrom
fix/sys-verification-value-not-unique
Jun 25, 2026
Merged

fix(identity): sys_verification.value must not be UNIQUE — breaks OIDC authorize (503)#2333
os-zhuang merged 1 commit into
mainfrom
fix/sys-verification-value-not-unique

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Bug

/api/v1/auth/oauth2/authorize (the cloud-as-IdP OP) returns HTTP 503 with:

UNIQUE constraint failed: sys_verification.value

better-auth's oauth-provider stores OIDC authorization codes in the verification table with value = a JSON blob ({type:"authorization_code", query:{…,state}, userId, sessionId, …}). That blob can legitimately repeat (same user+client+state on retry), but sys-verification.object.ts declared { fields: ['value'], unique: true } → the insert violates the constraint → 503.

Impact: the env→cloud OIDC SSO ("Continue with ObjectStack", ADR-0024 D3) loops forever — the cloud login SPA re-issues the signed authorize request every ~20s and never completes.

Fix

valueunique: false (keep the index for lookups; better-auth keys on identifier, not value).

Found via

Local browser E2E of the env-side SSO against a real cloud OP (anonymous env login → "Continue with ObjectStack"). Confirmed in the server log (SqliteError … SQLITE_CONSTRAINT_UNIQUE); dropping uniq_sys_verification_value in the live DB stopped the UNIQUE errors.

Follow-ups (separate)

  • Migration: existing control-plane DBs already have uniq_sys_verification_value; schema-sync is additive, so they need a one-off DROP INDEX.
  • Frontend: even with this fixed, the cloud login SPA does not navigate to the authorize success redirect (200-with-body) — the OIDC SSO still needs a frontend fix to complete. Filed separately.

🤖 Generated with Claude Code

…OIDC authorize

better-auth's oauth-provider stores OIDC authorization codes in the verification
table with `value` = a JSON blob (keyed by user + client + state) that can
legitimately repeat. The UNIQUE index on `value` makes
`/api/v1/auth/oauth2/authorize` fail with `UNIQUE constraint failed:
sys_verification.value` → HTTP 503, which breaks cloud-as-IdP SSO
("Continue with ObjectStack") entirely — the authorize loops forever.

better-auth keys verification lookups on `identifier` (indexed), not `value`,
so a non-unique index on `value` is sufficient.

Found via a local browser E2E of the env→cloud OIDC SSO flow (ADR-0024 D3).
NOTE: existing control-plane DBs already have `uniq_sys_verification_value`;
they need a migration to drop it (schema-sync is additive).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 25, 2026 5:19pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/platform-objects.

3 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/concepts/packages.mdx (via @objectstack/platform-objects)
  • content/docs/concepts/setup-app.mdx (via @objectstack/platform-objects)
  • content/docs/guides/packages.mdx (via @objectstack/platform-objects)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang

Copy link
Copy Markdown
Contributor Author

Confirmed required for the env→cloud OIDC SSO chain ("Continue with ObjectStack", ADR-0024 D3): without this, GET /api/v1/auth/oauth2/authorize returns 503 UNIQUE constraint failed: sys_verification.value. With the unique dropped (curl, valid cloud session, plain OIDC params) authorize cleanly 302s to the env callback with a code.

Verified end-to-end (curl + browser) together with the frontend companion objectstack-ai/objectui#2008 — the full flow now JIT-provisions the env sys_user and lands authenticated on the env /_console/home. (The previously-suspected env-runtime callback bug turned out to be a phantom — a stale single-use code during the frontend loop, fixed by #2008.)

Heads-up for existing control-plane DBs: schema-sync is additive and won't drop the existing UNIQUE(value) index — they'll need a DROP migration on top of this object-def change.

@os-zhuang
os-zhuang merged commit e8a81f0 into main Jun 25, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the fix/sys-verification-value-not-unique branch June 25, 2026 18:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant