Skip to content

convex-auth v2.4.1

Choose a tag to compare

@shlomokabareti shlomokabareti released this 18 Sep 14:29
· 100 commits to main since this release
63d0e98

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 (isCurrent computed server-side, revokeSession takes sessionId with 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-credentialId legacy 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_regression audit event (cloned-authenticator detection).
  • renamePasskey mutation via auth.renamePasskey, usePasskeys().rename, onRename prop on PasskeyManager.
  • passkey.maxPasskeysPerUser config (default 10), re-checked at verification time.
  • passkey.origin accepts string | string[]; attestationType, userVerification, residentKey, authenticatorAttachment configurable.
  • 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 carries credentialId so the minted session stays revocable with the passkey. Both usePasskeys hooks store the challenge token so ConvexVerifyTwoFactorForm completes the flow.
  • Passkey revocation paginates all lookups to exhaustion, attributes legacy sessions via stored-JWT identityId, and consumes in-flight pending challenges.
  • usePasskeys fetches ceremony options at invocation time, not mount — no stale challenges.
  • Audit events: passkey_registered, passkey_authenticated, passkey_renamed, passkey_revoked.
  • React Native / Expo: usePasskeys under @vortex-api/convex-auth/react-native/passkeys (optional react-native-passkeys peer). Configure passkey.origin per platform including android:apk-key-hash:<hash>.

Sessions & 2FA

  • listSessions no longer returns token; items carry server-computed isCurrent.
  • revokeSession takes { sessionId } with caller-ownership verification.
  • ConvexSessionList drops currentSessionToken (web + React Native). Migration: revokeSession({ token }) → revokeSession({ sessionId }); remove the currentSessionToken prop.
  • revokedAt enforced on session resolution, token-verify action, bearer /convex/token and /session, MCP OAuth authorize, OAuth account linking, and verifySession (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.
  • authAccounts gains by_user_provider_issuer; organization_members gains by_user_status.

Admin

  • Safe impersonation: short-lived audited sessions, IMPERSONATION_SESSION_DURATION_MS config, banner + stop in the React example.
  • createUser, setRole, setUserPassword, listUsers with search/filter/sort/pagination.
  • listAdminAudits filters (action, targetType, targetId, adminId, from, to); auditsFilters dashboard controls.
  • Member list/search/pagination, updateMemberRole, removeMember dashboard wiring.
  • User search + detail side panel via usersSearch, onViewUser, selectedUser.

React Native demo

  • Single react-native version across the workspace; Metro native extensions; Expo SDK 57 alignment; Uniwind theme init + accent-color patch; session JWT no longer rendered in the header.

Full Changelog: v2.3.0...v2.4.1