Skip to content

User Account Settings

User account settings are presented as a modal dialog accessible from the account menu via “My Account”. The modal uses the same split-pane layout as organization settings — sidebar navigation on the left, scrollable content on the right — with three tabs.

The modal is opened from the AccountMenu dropdown in the app shell. It can also be triggered programmatically via the settings modal state in AppShell.

Displays and edits the user’s personal information:

  • Avatar — Shows user initials as fallback
  • Display name — Editable text field with save feedback
  • Email — Read-only display (changed from Security tab)
  • Language — Locale selector (persisted per user)
authClient.updateUser({ name: "New Name" })

Security tab with password, email change, 2FA, passkeys, and session management

Comprehensive security management with six sections:

Three-field form: current password, new password, confirm password. Changing the password automatically revokes all other sessions.

authClient.changePassword({
currentPassword: "old",
newPassword: "new",
revokeOtherSessions: true,
})

Enter a new email address. A verification email is sent — the email is not changed until the user confirms the new address.

authClient.changeEmail({ newEmail: "new@example.com" })

Four-state flow:

State UI Action
Not enabled Password confirmation form authClient.twoFactor.enable({ password })
Setup QR code + 6-digit code input authClient.twoFactor.verifyTotp({ code })
Backup codes 8 single-use codes in 2-column grid Save codes (shown once)
Enabled Green status + disable button authClient.twoFactor.disable({ password })

Backup codes are generated during enable and displayed once — they cannot be retrieved again.

Conditional section — only shown when passkeys are enabled in system configuration.

  • Add passkey — Opens the browser’s WebAuthn credential creation dialog
  • List passkeys — Shows name and creation date for each registered passkey
  • Delete passkey — Remove a specific passkey
authClient.passkey.addPasskey()
authClient.passkey.deletePasskey({ id: passkeyId })

Link and unlink social provider accounts. Only shows providers enabled in system configuration.

Provider Available when
Google socialProviders.google enabled
GitHub socialProviders.github enabled
Apple socialProviders.apple enabled
Microsoft socialProviders.microsoft enabled
// Link
authClient.linkSocial({ provider: "google", callbackURL: "/settings" })
// Unlink
authClient.unlinkAccount({ providerId })

Cannot unlink the last authentication method — at least one sign-in method must remain.

Lists all active sessions with browser/device info (parsed from user agent) and last active date. The current session is marked with a badge.

// List all sessions
const sessions = authClient.multiSession.listDeviceSessions()
// Sign out all other devices
authClient.revokeOtherSessions()

Maximum: 5 concurrent sessions per user (enforced by backend).

Lists all organizations the user belongs to with name, slug, and role badge (Owner, Admin, Member).

Leave organization — Available for non-sole-owners. If the user is the only owner, the button is disabled with a tooltip: “Transfer ownership to another member before leaving.”

authClient.organization.leave({ organizationId })

Located in the Security tab danger zone. Requires the user to type the confirmation phrase Delete my account into a text input.

Restrictions: Cannot delete account if the user is the sole owner of any organization. Must transfer ownership or delete the organization first.

Deletion process:

  1. Revokes all user sessions
  2. Removes all organization memberships
  3. Bans the user account
  4. Anonymizes PII: name → [deleted-{userId}], email → deleted-{userId}@redacted.local
  5. Audit logged
  6. Redirects to sign-in page
authClient.deleteUser({ callbackURL: "/sign-in" })

Several sections are conditionally displayed based on system configuration:

Flag Controls
auth.passkeyEnabled Passkey section visibility
socialProviders.{provider}.enabled Per-provider connect/disconnect
security.passwordMinLength Password validation (default: 10)
security.sessionDuration Session TTL (default: 24 hours)
File Purpose
packages/web-shell/src/components/settings/user-settings-modal.tsx Modal shell and tab routing
packages/web-shell/src/components/settings/tabs/profile-tab.tsx Name, avatar, and language editing
packages/web-shell/src/components/settings/tabs/security-tab.tsx Password, 2FA, passkeys, social, sessions, account deletion
packages/web-shell/src/components/settings/tabs/organization-tab.tsx Org membership list and leave
packages/web-shell/src/components/account-menu.tsx Modal trigger in app shell
packages/web-shell/src/components/shared/danger-zone.tsx Reusable destructive action component
packages/backend/src/convex/modules/core/users/user_api.ts User deletion and PII anonymization
packages/backend/src/convex/lib/core/auth/convex_auth.ts BetterAuth configuration (2FA, passkeys, social, sessions)