Skip to main content

Authentication Methods

Cavos supports multiple authentication methods:
MethodIdentityUse Case
Google OAuthEmail, name, profile pictureQuick social login
Apple OAuthEmail (optionally hidden), namePrivacy-focused social login
Email/PasswordEmail verified with linkTraditional authentication
Passkey-OnlyAnonymous, no emailPrivacy-first apps
All authentication methods create a self-custodial StarkNet wallet tied to your identity. (…)

Social Login (Google/Apple)

(…) 17: All authentication methods create a self-custodial StarkNet wallet tied to your identity. 18: 19: ## Social Login (Google/Apple) 20: 21: ### Login with Google 22: 23: tsx 24: import { useCavos } from '@cavos/react'; 25: 26: function LoginButton() { 27: const { login, isAuthenticated, user, address } = useCavos(); 28: 29: if (isAuthenticated) { 30: return ( 31: <div> 32: <p>Welcome, {user?.name}</p> 33: <p>Wallet: {address}</p> 34: </div> 35: ); 36: } 37: 38: return ( 39: <button onClick={() => login('google')}> 40: Login with Google 41: </button> 42: ); 43: } 44: 45: 46: ### Login with Apple 47: 48: tsx 49: <button onClick={() => login('apple')}> 50: Login with Apple 51: </button> 52: 53: 54: ### Social Login Flow 55: 56: 1. User clicks login button 57: 2. SDK redirects to Google/Apple OAuth 58: 3. User authenticates with their account 59: 4. Provider redirects back with JWT token 60: 5. SDK derives wallet address from OAuth identity 61: 6. Wallet is ready to use (session key is registered on first transaction) 62: 63:
64: Your wallet address is deterministically derived from your OAuth identity (Google/Apple user ID). Same account = same wallet address across devices. 65:
66: 67: ## Email/Password Authentication (Firebase) 68: 69: For traditional email/password authentication using Firebase. Note: Email verification is required before you can access your wallet. 70: 71: ### 1. Registration 72: 73: tsx 74: import { useCavos } from '@cavos/react'; 75: 76: function RegisterForm() { 77: const { register, isLoading } = useCavos(); 78: const [email, setEmail] = useState(''); 79: const [password, setPassword] = useState(''); 80: const [error, setError] = useState(''); 81: 82: const handleRegister = async () => { 83: try { 84: await register('firebase', { email, password }); 85: // User receives verification email automatically 86: alert('Check your email to verify your account!'); 87: } catch (err) { 88: setError(err.message || 'Registration failed'); 89: } 90: }; 91: 92: return ( 93: <form onSubmit={(e) => { e.preventDefault(); handleRegister(); }}> 94: <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" /> 95: <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" /> 96: <button type="submit" disabled={isLoading}>Register</button> 97: {error && <p>{error}</p>} 98: </form> 99: ); 100: } 101: 102: 103: ### 2. Login & Verification 104: 105: If a user tries to login without verifying their email, the SDK will throw an EmailNotVerifiedError. 106: 107: tsx 108: const handleLogin = async () => { 109: try { 110: await login('firebase', { email, password }); 111: } catch (err) { 112: if (err.name === 'EmailNotVerifiedError') { 113: // User MUST verify email before proceeding 114: alert('Please verify your email first.'); 115: } 116: } 117: }; 118: 119: 120: ### 3. Verification Management 121: 122: You can manually check verification status or resend the email: 123: 124: tsx 125: const { cavos } = useCavos(); 126: 127: // Check if verified 128: if (!await cavos.isEmailVerified(email)) { 129: // Resend email 130: await cavos.resendVerificationEmail(email); 131: } 132: 133: 134:
135: Verification emails are rate-limited to 60 seconds. 136:
Email verification is required before login. Users cannot access their wallet until they click the verification link in their email.
Your wallet address is derived from your Firebase User ID. Same email = same wallet address, even if you reset your password.

Passkey-Only Authentication

For apps that don’t need user identity, use passkey-only mode:
import { useCavos } from '@cavos/react';

function PasskeyButton() {
  const { createWallet, address, isLoading } = useCavos();

  if (address) {
    return <p>Wallet: {address}</p>;
  }

  return (
    <button onClick={createWallet} disabled={isLoading}>
      Continue with Passkey
    </button>
  );
}

How It Works

When createWallet() is called without prior authentication:
  1. SDK checks for existing passkey wallet
  2. If found, prompts for biometric authentication
  3. If not found, creates new passkey and wallet
  4. Wallet is deployed gaslessly
Passkey-only wallets can only be recovered on devices that have the passkey synced (iCloud Keychain, Google Password Manager). Users should understand this limitation.

Session Management

Check Authentication State

const { isAuthenticated, user, address, isLoading } = useCavos();

if (isLoading) {
  return <Spinner />;
}

if (!isAuthenticated) {
  return <LoginButton />;
}

// User is authenticated

Logout

const { logout } = useCavos();

async function handleLogout() {
  await logout();
  // User is now logged out, wallet is cleared
}

Session Restoration

The SDK automatically restores sessions on page load:
  • OAuth sessions: Restored from browser storage
  • Passkey wallets: Restored from local storage (requires biometric)

Error Handling

Email Not Verified Error

When a user tries to login without verifying their email:
try {
  await login('firebase', { email, password });
} catch (error) {
  if (error.name === 'EmailNotVerifiedError') {
    // Show resend verification button
    const { cavos } = useCavos();
    await cavos.resendVerificationEmail(error.email);
  }
}

Invalid Credentials

try {
  await login('firebase', { email, password });
} catch (error) {
  if (error.message?.includes('auth/wrong-password')) {
    showError('Invalid email or password');
  } else if (error.message?.includes('auth/user-not-found')) {
    showError('No account found with this email');
  }
}

Rate Limiting

If a user tries to register multiple times:
try {
  await register('firebase', { email, password });
} catch (error) {
  if (error.error === 'rate_limited') {
    showError(`Please wait ${error.wait_seconds} seconds before trying again`);
  }
}

Account Deletion

To permanently delete a user’s account and wallet:
const { deleteAccount } = useCavos();

async function handleDeleteAccount() {
  if (confirm('This action is irreversible. Delete account?')) {
    await deleteAccount();
  }
}
Account deletion removes the wallet from Cavos servers. The on-chain account still exists but the private key is irrecoverable.