Repository navigation
Releases: VortexNYC/convex-auth
Release list
@vortex-api/convex-auth@3.2.0
Minor Changes
-
c1acd65: Add global-scope webhook endpoint lifecycle operations.
createWebhookEndpointaccepts org-less (platform-wide) endpoints, but the existingsetWebhookEndpointStatus/deleteWebhookEndpointrequire anorganizationIdand fail closed on org-less rows — so global endpoints could be created but never disabled, archived, or deleted.New component functions mirror the org-scoped set:
listGlobalWebhookEndpoints,setGlobalWebhookEndpointStatus, anddeleteGlobalWebhookEndpoint. They resolve through a dedicatedrequireGlobalWebhookEndpointguard that rejects org-scoped endpoints, matching the org ops which already reject org-less ones — each scope fails closed on the other. -
1bd3bc6: feat(auth): Google One Tap sign-in (#206)
Adds
convexAuth({ oneTap })— verifies a Google Identity Services ID token
against Google's JWKS via the existingcreateGoogleProviderpath (RS256,
iss/aud/exp, optionalhd), then provisions the samegoogleidentity as
redirect OAuth so both flows resolve to one account.- Server action
signInOneTapwithdisableSignUp,
disableImplicitSignUp,requireEmailVerification, nonce claim pinning,
and per-subject rate limiting (on by default) oneTap: trueinheritsclientId/hd/maxTokenAge/fetchImplfrom
oauth.google;clientSecretis never requireduseAuthActions().signInOneTap({ idToken })on React and React Native,
signIn.oneTap({ idToken })on the Better Auth client- SSR cookie-mode support via the
signInOneTapproxy intent and Next.js
serialization
- Server action
-
1ad578f: Add phone-number sign-in via SMS OTP (
convexAuth({ phone })→sendPhoneOtp/verifyPhoneOtp,signIn.phoneOtp). Numbers normalize to E.164, land onusers.phoneNumber/phoneNumberVerifiedwith aby_phoneNumberindex, and provision aphoneOtpidentity that fails closed on collisions. Session-gatedphone-verificationcodes verify an existing account's number and link thephoneOtpidentity. ReusescreateTwilioSmsOtpSender; optional per-phone rate limiting on sends and verifies. Migration CLI now writesusername/displayUsername/phoneNumber/phoneNumberVerifiedonto migrated users instead of dropping them. -
7110b45: Add username/password authentication.
convexAuth({ username })enablessignUpUsername/signInUsernameactions,POST /api/auth/sign-up/usernameand/api/auth/sign-in/usernameHTTP routes,signUpUsername/signInUsernameSSR proxy intents,useAuthActions().signUpUsername/signInUsername, andclient.signUp.username/client.signIn.usernameon the Better Auth-shaped client.Users gain optional
username(normalized, unique viaby_username) anddisplayUsername(original casing) fields.provisionFromIdentitynow rejects username collisions inside the serialized mutation withduplicateField: "username" | "email", and exposesgetUserAndAccountByUsername. Username identities useprovider: "username",issuer: "native"and are never linkable by email claim.Sign-in shares the email/password pipeline: migrated bcrypt credentials rehash to argon2id on first verify (CAS-guarded), per-username rate limiting, and the same 2FA / trusted-device challenge flow. Optional
usernameValidator, length bounds,checkBreach,requireVerifiedEmail(for attached emails),captcha, andonExistingUserSignUpare supported.
Patch Changes
-
5ffc617: fix(component): use
by_adminindex inlistAdminAuditswhenadminIdfilter is set — previously scanned the whole audit table on every filtered page -
6be730d: Fix proxied password/username sign-in rejecting the cookie-substituted
landingVerifierwithArgumentValidationError. The SSR proxy substitutes the landing verifier from its cookie intosignIn,signInUsername, andcallbackargs; the two password actions never declared the field, so every cookie-mode sign-in 400'd once a verifier cookie existed (the middleware mints one on any navigation). Both actions now accept and echo it into the session result, matching thenativeAuthSessionValidatorcontract used by the component's redirect-stamping routes. Also fixesgetConvexNextjsOptionsemitting{ url: undefined }when callers passconvexUrlas a present-but-unset key —convex/nextjswarns "deploymentUrl is undefined" on every call with an explicitundefinedand will treat it as an error in a future release; omitting the key preserves theNEXT_PUBLIC_CONVEX_URLenv fallback cleanly. -
8e8f8e2: Redirect with
unsupported_providerinstead of an unhandled 500 when the OAuth signin or callback route is hit with an unconfigured provider id. -
0b29e27:
convex-auth preflightnow validatesconvex/auth.config.ts— presence plus the canonicalcreateConvexAuthProviderwiring — via a newproviderConfigPathbackend-setup option wired in the CLI'sbackendSetupFromConvexDir. The existing "Convex auth config" slot validatesauth.ts(theconvexAuth()callsite) and its default path is corrected toconvex/auth.tsto match; previously it pointed atconvex/auth.config.tswhile requiring aconvexAuthsnippet that file never contains, so programmatic callers with defaults could false-fail it.Nothing validated
auth.config.tsbefore this change, which let a real consumer-facing bug ship: without the provider registration, Convex rejects any request carrying a session JWT as caller auth withNoAuthProviderbefore the function runs — proxiedsignOutcleared cookies and returned 400 while the server-side session stayed valid, so a stolen cookie pair remained live after "logout".convex-auth check/bug-report already diagnosed the file; preflight now fails on its absence too.Heads-up for consumers running
convex-auth preflightorauth:preflight: a previously green run will now fail ifconvex/auth.config.tsis missing or lackscreateConvexAuthProvider— that failure is the check working (the file is required wiring);--skip-backend-setupremains the escape hatch. -
0b68330: fix(runtime): map expected 2FA errors to 401/400 on HTTP routes —
Invalid two factor code,Invalid two factor token,Not enrolled, andUnauthorizedpreviously surfaced as500 unknownon/api/auth/two-factor/* -
4cb8d26: Make pending two-factor challenges retryable: a wrong TOTP or backup code
no longer consumes the challenge — it records a failed attempt and the user
can retry. Verification attempts are reserved atomically before the code is
checked, so after 5 attempts the challenge stops accepting guesses even
under concurrent requests.authVerificationCodesgains an optional
failedAttemptsfield and the component exposesreserveVerificationAttempt.
@vortex-api/convex-auth@3.1.0
Minor Changes
-
96de151: feat: Clerk/WorkOS migration foundation —
verifyPasswordnow accepts imported bcrypt digests ($2a$/$2b$/$2y$via hash-wasm, isolate-safe) and any verified non-native or below-floor credential lazily rehashes to argon2id with a CAS guard; new@vortex-api/convex-auth/migrationsexport ships the normalizers (Clerk API+CSV, WorkOS) plus idempotent internalmigrateOrganization/migrateMembershipwriters with role seeding, invited→active promotion, and migration-marker attach guards -
f68d288: Component contract tightening:
- Passkey options require a non-empty
origin—generatePasskeyRegistrationOptionsandgeneratePasskeyAuthenticationOptionsnow reject calls withoutorigin(or with an empty string/array), so every new challenge records its expected origin. Challenges created before this change still verify via the caller-supplied fallback during their TTL. The runtime wrapper already requiresoriginin config; direct component callers must now pass it. - Return validators filled in —
generatePasskeyRegistrationOptions(v.any()→ record),native/accounts(updateAccountTokens→ null,createAccount→ id,getAccountBySubject→ doc|null),native/codes(all four functions). rateLimitshonesty —recordAttempt/checkRateLimitno longer emitcount(the backing rate-limiter doesn't expose bucket counts; it was always0).countis now optional in the return type.cleanupExpiredRateLimitsdocumented as a kept no-op for contract compatibility.
- Passkey options require a non-empty
-
ce51bce: Add the Hono server adapter —
@vortex-api/convex-auth/hono.convexAuthMiddlewareis the whole server surface in oneapp.use("*"): it proxiesPOST /api/authauth intents, lands OAuth/magic-link session triples as HttpOnly cookies, rotates near-expiry tokens onto downstream responses (rebuilding immutable responses when needed), and strips auth cookies from cross-origin requests.convexAuthProxyHandlermounts the proxy as an explicit route instead. Session helpers (getConvexAuthSession,getConvexAuthToken,convexAuthCookieState,getAuthServerState) take the Hono context and are rotation- and revocation-aware. Works on@hono/node-server, Bun, Deno, and any fetch-runtime Hono supports.honois an optional peer (>=4); the adapter is type-only against it.The request-scoped session bookkeeping (rotation overrides, CORS-strip tracking,
verifySessionmemoization) moved from the TanStack adapter into the sharedssr/substrate — it was already framework-agnostic;./tanstack-start/serverre-exports it unchanged. -
f626e8f: Declare
engines.node >=22and drop Node 20 from the tested matrix.Node 20 reached end-of-life in April 2026 and no longer receives security fixes. The library's Node-touching surface (server-side helpers used inside Next.js handlers, TanStack server functions, and SSR glue) is now tested on Node 22 and Node 24 only. Consumers on Node 20 will see an install-time
engineswarning rather than a silent unsupported environment; the deployed component code is unaffected — it runs in the Convex V8 isolate, which is not Node at all.
Patch Changes
-
cf4ef80: Component review hardening — three correctness fixes:
- OAuth
requireEmailVerificationordering: the check now runs beforeprovisionFromIdentityand account-token writes, so a denied sign-in no longer leaves orphaned user/identity rows or overwrites stored OAuth tokens on a rejected request. provisionFromIdentitylinking invariant: implicit email-match linking now requiresidentity.emailVerified === true— callers can no longer link an unverified provider email into an existing account via the defaultallowLink: true. ThetrustedProvidersescape is preserved through a new explicitallowUnverifiedEmailLinkarg. Provisions can no longer downgrade a verified user'semailVerifiedflag (monotonic).- Admin
listUserssearch: partial substring search now works — the previous path exact-matchedby_email/by_namethen substring-filtered the already-exact set, so partial terms silently returned nothing. Search now paginates withfilterWith(matching the admin audit pattern) and supports cursors.
- OAuth
-
d0ea688: chore: move
set-cookie-parserto devDependencies — it is only used by the internal conformance harness, so it no longer lands in consumer installs -
fa5582f: perf: index sweep — passkey revocation now reads
authSessionsthroughby_credential_idinstead of scanning every session for the user, and 17 never-referenced index declarations (16 unique names) are removed acrossusers,auth_identities,auth_admin_audits,webhook_deliveries,auth_passkeys,organization_members,agent_auth_audit_events,auth_md_*, andmcp_oauth_signing_keys(one-line re-add if a query path lands for them) -
d0ea688: Bump internal dependencies:
@convex-dev/rate-limiter0.3 → 0.4 (additive release —RateLimiterconstructor,limit, andcheckAPIs unchanged; verified against the full rate-limit suite) andconvex-helpers0.1.80 → 0.1.124. Also bumps@simplewebauthn/server,jose,oauth4webapi, andotpauthto latest patches.
@vortex-api/convex-auth@3.0.1
Patch Changes
- fix(nextjs): translate
:name(.*)legacy wildcards to{*name}—createRouteMatcherno longer throws on patterns like/:locale(.*)under path-to-regexp v8
v3.0.0
Breaking changes
OidcProviderStorageAdapter.getSessionByTokenrequiresexpiresAt(#334) — presence-based enforcement meant a lazy adapter returning{ userId }silently skipped session expiry. Custom storage adapters must returnexpiresAt(ms).- Deprecated provider args removed —
nativeEmailAndPasswordno longer accepts top-levelsendVerificationEmailOnSignUp/sendVerificationEmailOnSignIn; useemail.sendOnSignUp/email.sendOnSignIn. resolvePermissionOverrideadapter removed — express permission variance as roles;expandPermissionsis unchanged.- Session fallback removals —
revokePasskeySessionsdrops pre-credentialIdcompat (#337); session refresh no longer readsidentityIdfrom JWT claims (#373);revokeSessionFamilyno longer matchesfamilyId-less sessions (#374). Deploy the latest 2.x first if upgrading from < 2.5.x so live sessions backfill. path-to-regexpv8 — advertised wildcard forms (X/(.*), gluedX(.*)) keep matching identically via internal translation to{*splat}; unnamed groups like/(a|b)/now throw a descriptive error atcreateRouteMatcherconstruction.- Stricter redirect validation — the OAuth
signInaction validatescallbackURL/errorURL/newUserURLagainst the trusted-origins allowlist; protocol-relative URLs andSec-Fetch-Sitebypasses closed. - Landing verifier binding — session-triple landings require the
__convexAuthLandingVerifiercookie from the initiating browser; cross-browser landings get?error=landing_verifier_mismatchunlessrequireLandingVerifier: false.
Migration guide: docs/(clients-and-migration)/v3-migration.md
Added
- TanStack Start SSR adapter —
@vortex-api/convex-auth/tanstack-start(+/server): app-origin HttpOnly cookie sessions, server-confidential refresh token, intent-based/api/authproxy. @vortex-api/convex-auth/test—register,convexAuthTest,modules,schemafor consumerconvex-testharnesses; wired into the component conformance suite.- API keys —
allowedIpRangesonissueApiKey/issueServiceOwnedApiKeyin the feature-gated component (parity with the monolith).
Fixed
revokeOtherSessionsspares the caller's whole session family (excludeFamilyIdonrevokeSessionsForUser).- Family revocation scoped to rotated-token replay — administrative revocation replays no longer nuke the family.
- SSR/auth hardening sweep — redirect allowlists, CSRF, CORS landings, response forwarding (7 issues).
- Index cleanup — 8 covered prefix indexes dropped (apply on next
convex dev/push); creation-ordered list endpoints keep dedicated indexes.
Published with npm provenance (sigstore).
convex-auth v2.5.2
Patch Changes
Ship complete component source in the published tarball — #351
The 2.5.1 tarball still could not install cleanly for consumers: files shipped src/convex-runtime/** and the nine convex.config.ts files, but not the component implementation itself — schema.ts, _generated/, and every function module under src/component/ — nor transitive deps (src/compat, src/mcp, src/core). Bundling the convex entry failed with Could not resolve "../../component/_generated/server.js" and the component could not deploy.
files now ships src/** wholesale (minus *.test.*, *.vitest.ts, *.type-test.ts), matching the upstream @convex-dev/auth source-publish model. Verified by bundling every component and runtime source file from the packed tarball under esbuild.
convex-auth v2.5.1
Minor Changes
Next.js SSR adapter — #343
Add a Next.js SSR adapter with HttpOnly cookie sessions.
- New:
packages/auth/src/nextjsexports the App Router surface — a route-handler proxy (/api/auth), middleware for protected routes and proactive refresh, server-side session reads, and server-action support. Sessions live in HttpOnly cookies; tokens never reach client JS. - Demo:
examples/nextjsis a working App Router app verified end-to-end against a local Convex deployment. - SSR renders verify the session server-side and fail closed: expired or revoked sessions redirect to sign-in instead of flashing authenticated UI.
Patch Changes
Session-rotation convergence — #343
- Two parallel requests presenting the same refresh token (the normal SSR pattern) no longer destroy the session.
rotateSessionmarksrotatedAtand reports"converge"inside a 15s grace window;convergeSessionmints a bounded sibling session+refresh pair in the same family. Bounds: ≤8 grace redemptions per predecessor, ≤10 live sessions per family, convergence requires a live member. updateSessionnow resolves the session's identity — OAuth/passkey sessions refresh correctly.authSessionsgainsidentityId;authRefreshTokensgainsrotatedAt/graceRedemptions.
Family-aware revocation — #349, #344
signOut,stopImpersonation, user-facingrevokeSession, and adminrevokeSessionall revoke the whole session family.revokeSessionsForUsernow marks revoked sessions' refresh tokens too.- Audit:
session.sign_out(voluntary),session.revoke(sessions-list),refresh_token_reuse(replay detection) — admin actions stay onauth_admin_audits.
Published package fix — #345 (thanks @david-potgieter)
- The
filesallowlist shipped only a handful ofconvex-runtimemodules — installs failed withCould not resolve "./convexAuth.js"and friends. The tarball now ships the fullsrc/convex-runtime/**tree;convex/typesexport conditions point atsrc/convex-runtime/index.ts.
convex-auth v2.4.1
Highlights
- Argon2id password hashing —
argon2id-wasm(Rust → WASM), ~10x faster in the Convex isolate. New hashes in standard PHC format ($argon2id$v=19$m=19456,t=2,p=1$); legacy packed, Better Auth scrypt, and PBKDF2 hashes still verify — no migration needed. - Passkeys, web + React Native/Expo — registration, sign-in, revocation, and rename, bound to the caller's identity. Conditional-UI autofill on web;
react-native-passkeys-backed ceremonies on iOS/Android verified by the same server actions. Validated end-to-end on both platforms. - Session hardening — every session-validating path now rejects revoked sessions; session lists never expose raw tokens (
isCurrentcomputed server-side,revokeSessiontakessessionIdwith an ownership check); 2FA pending challenges are opaque hashed tokens, not JWTs. - Passkey revocation cascade — sessions and refresh tokens minted by a passkey record
credentialId; revoking the passkey (or detecting a cloned authenticator via signature-counter regression) revokes them all, across arbitrarily large histories including pre-credentialIdlegacy rows. - Admin dashboard — impersonation with audited sessions, user search + detail panel, organization member/role management, audit-log filters.
- Query exhaustion fixes — all revocation and code-consume paths paginate to exhaustion; sessions, refresh tokens, and live codes beyond the first index page can no longer survive revocation.
What's Changed
Password hashing
- Switch password hashing to
argon2id-wasm; WASM init failures now surface as errors instead of reading as "wrong password".
Passkeys
- Passkey management (register, list, revoke, rename) bound to
ctx.auth.getUserIdentity(). - Non-increasing signature counter revokes the passkey and writes a
passkey_counter_regressionaudit event (cloned-authenticator detection). renamePasskeymutation viaauth.renamePasskey,usePasskeys().rename,onRenameprop onPasskeyManager.passkey.maxPasskeysPerUserconfig (default 10), re-checked at verification time.passkey.originacceptsstring | string[];attestationType,userVerification,residentKey,authenticatorAttachmentconfigurable.usePasskeys({ autofill: true })enables WebAuthn conditional-UI sign-in.- Challenges record
rpID, accepted origins, effective identifier, and UV policy at generation; verification uses stored values. - Relaxed-UV passkey sign-in on a 2FA account returns
twoFactorRedirect; the pending challenge carriescredentialIdso the minted session stays revocable with the passkey. BothusePasskeyshooks store the challenge token soConvexVerifyTwoFactorFormcompletes the flow. - Passkey revocation paginates all lookups to exhaustion, attributes legacy sessions via stored-JWT
identityId, and consumes in-flight pending challenges. usePasskeysfetches ceremony options at invocation time, not mount — no stale challenges.- Audit events:
passkey_registered,passkey_authenticated,passkey_renamed,passkey_revoked. - React Native / Expo:
usePasskeysunder@vortex-api/convex-auth/react-native/passkeys(optionalreact-native-passkeyspeer). Configurepasskey.originper platform includingandroid:apk-key-hash:<hash>.
Sessions & 2FA
listSessionsno longer returnstoken; items carry server-computedisCurrent.revokeSessiontakes{ sessionId }with caller-ownership verification.ConvexSessionListdropscurrentSessionToken(web + React Native). Migration:revokeSession({ token })→revokeSession({ sessionId }); remove thecurrentSessionTokenprop.revokedAtenforced on session resolution, token-verify action, bearer/convex/tokenand/session, MCP OAuth authorize, OAuth account linking, andverifySession(no more arbitrary-active-session fallback).- Session-family revocation,
revokeSessionsForUser, refresh-token revocation, password-reset revoke, and verification-code consume/revoke paths all paginate to exhaustion. authAccountsgainsby_user_provider_issuer;organization_membersgainsby_user_status.
Admin
- Safe impersonation: short-lived audited sessions,
IMPERSONATION_SESSION_DURATION_MSconfig, banner + stop in the React example. createUser,setRole,setUserPassword,listUserswith search/filter/sort/pagination.listAdminAuditsfilters (action,targetType,targetId,adminId,from,to);auditsFiltersdashboard controls.- Member list/search/pagination,
updateMemberRole,removeMemberdashboard wiring. - User search + detail side panel via
usersSearch,onViewUser,selectedUser.
React Native demo
- Single
react-nativeversion across the workspace; Metro native extensions; Expo SDK 57 alignment; Uniwind theme init +accent-colorpatch; session JWT no longer rendered in the header.
Full Changelog: v2.3.0...v2.4.1
convex-auth v2.3.0
What's Changed
- feat(oauth-demo): authz hardening + security scanning by @shlomokabareti in #251
- chore(deps): bump actions/checkout from 4.4.0 to 7.0.1 by @dependabot[bot] in #235
- chore(deps): bump actions/setup-node from 4.4.0 to 7.0.0 by @dependabot[bot] in #238
- chore(deps): bump github/codeql-action/analyze from 5ba2889ada762081db2c4f32a729827dce632c7b to 6f5948dfacef28e207b48d0905cf90c03365536d by @dependabot[bot] in #236
- chore(deps-dev): bump vitest from 4.1.11 to 5.0.0 in /packages/auth by @dependabot[bot] in #234
- chore: use vortex.nyc author email by @shlomokabareti in #208
- chore(deps): bump pnpm/action-setup from f40ffcd9367d9f12939873eb1018b921a783ffaa to b906affcce14559ad1aafd4ab0e942779e9f58b1 by @dependabot[bot] in #239
- docs: update README to match current docs and native runtime by @shlomokabareti in #256
- feat/passkeys by @shlomokabareti in #257
- feat: wire appearance provider and sign-out trigger into React demo by @shlomokabareti in #258
- feat/generic oauth by @shlomokabareti in #259
- test: add handleSignIn coverage for generic OAuth provider by @shlomokabareti in #260
- feat: OIDC discovery, JWKS, and ID-token verification for generic OAuth by @shlomokabareti in #261
- test: full generic OIDC handleCallback coverage and demo wiring by @shlomokabareti in #262
- feat/org consumer wiring by @shlomokabareti in #264
- feat(api-keys, service-principals): consumer surfaces, hooks, and React demo by @shlomokabareti in #265
- feat(webhooks): wire consumer surface and demo tab by @shlomokabareti in #266
- fix(webhooks): clear stale delivery state on retry and delivery by @shlomokabareti in #268
- fix(organizations): accept imageUrl from workspace creation form by @shlomokabareti in #267
- feat(auth): support AUTH_REDIRECT_URL env override for OAuth redirect base by @shlomokabareti in #263
- feat(auth): OIDC provider authorization-code + PKCE slice by @shlomokabareti in #269
- chore: version packages by @shlomokabareti in #270
- docs: OIDC provider guide and full-feature React demo README by @shlomokabareti in #271
- feat/anonymous by @shlomokabareti in #272
- chore: scaffold better-auth migration demo by @shlomokabareti in #273
- chore(react-native): update demo env docs for new auth features by @shlomokabareti in #274
- fix(docs, package): repair first-run docs, package metadata, and demo safety by @shlomokabareti in #275
- chore(examples): rename react-native demo to react-native-web by @shlomokabareti in #276
- ci(docs): fix unscoped package refs, add docs-smoke and coverage by @shlomokabareti in #277
- feat(examples): add a real Expo / React Native demo by @shlomokabareti in #278
- feat(auth,examples): React Native Uniwind conversion, full auth flows, docs by @shlomokabareti in #281
- fix(rn): React Native sign-in autofill, OAuth flow, and deep-link handling by @shlomokabareti in #282
- chore: version packages by @shlomokabareti in #283
- fix(rn): migrate React Native example and auth screens to Uniwind by @shlomokabareti in #285
- feat(rn): Uniwind-first dark-mode multi-platform React Native auth UI by @shlomokabareti in #284
- fix(rn): use accent-muted-foreground for placeholder text color by @shlomokabareti in #286
- fix(rn): use accent-* for ActivityIndicator color and remove nested FlatList in signed-in view by @shlomokabareti in #287
- chore: add changeset for release by @shlomokabareti in #288
- docs: add privileged ConvexAdminDashboard spec by @shlomokabareti in #290
- feat/admin core by @shlomokabareti in #291
- feat(users-admin): list, ban, unban and remove users by @shlomokabareti in #293
- feat(sessions-admin): list, get, revoke and revoke-all sessions by @shlomokabareti in #294
- feat(organisations-admin): list, get, manage members and roles for organizations by @shlomokabareti in #296
- feat/admin dashboard ui by @shlomokabareti in #297
- chore: version packages by @shlomokabareti in #299
Full Changelog: v2.0.5...v2.3.0
convex-auth v2.0.5
What's Changed
- Hardened
examples/oauthConvex wrappers to enforce caller identity and organization membership before listing, creating, revoking, or rotating organizations, sessions, API keys, service principals, webhooks, and audit events. - Added
examples/oauth/convex/authz.tshelpers (requireCaller,requireMatchingUserId,requireOrganizationMembership). - Added repository security scanning and CI:
pnpm run scan:security(deps, secrets, SAST, leaks).github/workflows/security-audit.yml- Semgrep, TruffleHog, Secretlint integration
pnpm-audit-exceptionsfor unfixableimage-sizetransitive advisories
- Bumped
convex-authto 2.0.5.
Verification
pnpm run check✅pnpm run typecheck✅pnpm run build✅pnpm test(1275 tests) ✅pnpm run scan:security✅- Live Browser-Use IDOR probes against
perfect-dragon-698rejected cross-user / cross-organization access.
convex-auth v2.0.4
What's changed
- Remove module-scope JWT private-key/JWKS caching so rotated keys take effect immediately and warm processes cannot sign with stale material.
- Add the missing
convex/auth.config.tsnative Convex auth provider wiring in the OAuth demo. - Share the pending 2FA challenge token through
ConvexAuthProvidercontext so the sign-in page and reusable verification form stay in sync. - Improve
toErrorinconvex-auth-client.tsto preserve string/object messages. - Increase JWT
iatfuture-clock skew leeway. - Update
mintOAuthStatefor the newgetJwtPrivateKeyreturn shape and include the key id in the header. - Clean up demo lint warnings and harden forgot/reset/verify-email response handling.
Verification
pnpm run check,typecheck,build,test(1275 tests),lint,lint:convex,scan:secretsall pass locally.convex-auth checkandconvex-auth preflightpass forexamples/oauth.- Browser (Safari MCP): 2FA TOTP sign-in, backup codes, sessions, API keys, service principals + verify-as-session, webhooks, audit, and preflight UI all verified.