Skip to main content
For Convex, Ave’s id_token is validated by Convex itself. For a custom backend (Hono, Express, Elysia, etc.) backed by Postgres or SQLite, you validate the JWT on each request and map sub (Ave identity UUID) to your users table.

Verify id_token on the server

Use verifyAveIdToken from @ave-id/sdk/server — it wraps JWKS verification and checks aud against your registered clientId. Shortcut — parse the header and verify in one step:
Or use verifyAveIdToken on the raw JWT string. Pass the same id_token your SPA would send in the Authorization header. Do not accept access_token_jwt as a substitute for identity unless you intentionally validate the API JWT audience — for app users, id_token is the right signal.

Drizzle upsert (Postgres or SQLite)

Example: one row per Ave identity, keyed by ave_identity_id.
SQLite / dialect differences: use your driver’s upsert form, or onConflictDoNothing then findFirst by aveIdentityId, or try/catch on unique constraint and findFirst on retry. Use a unique index on ave_identity_id. If you need a stable ID across Ave identities for one human user, consider the user_id scope and separate columns — see Convex custom auth for how sub vs user_id differ.

Scopes

Request openid profile email offline_access for SPAs that refresh tokens; the server only needs the Authorization: Bearer value carrying the id_token (or your own session cookie after establishing trust once).
Last modified on April 19, 2026