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
Magic LinkEmailPasswordless email login
All methods create a self-custodial Starknet wallet tied to your identity. The wallet address is deterministically derived from your OAuth sub claim and a per-app salt — the same account produces the same address across devices.

Social Login (Google / Apple)

Login with Google

import { useCavos } from '@cavos/react';

function LoginButton() {
  const { login, isAuthenticated, user, address } = useCavos();

  if (isAuthenticated) {
    return (
      <div>
        <p>Welcome, {user?.name}</p>
        <p>Wallet: {address}</p>
      </div>
    );
  }

  return (
    <button onClick={() => login('google')}>
      Login with Google
    </button>
  );
}

Login with Apple

<button onClick={() => login('apple')}>
  Login with Apple
</button>

How Social Login Works

  1. User clicks the login button
  2. SDK opens a new tab to the Google/Apple OAuth page
  3. User authenticates with their account
  4. The auth tab writes the result to localStorage and closes
  5. SDK derives the wallet address from the OAuth identity (sub + per-app salt)
  6. Account deployment + session registration happen automatically in the background
  7. walletStatus.isReady becomes true when setup is complete
Your wallet address is deterministically derived from your OAuth identity. Same Google/Apple account = same wallet address across all devices.

Send a passwordless login link to a user’s email. Resolves immediately after the email is sent; authentication completes in the background when the user clicks the link.
import { useCavos } from '@cavos/react';

function MagicLinkForm() {
  const { sendMagicLink, isAuthenticated, address } = useCavos();
  const [email, setEmail] = useState('');
  const [sent, setSent] = useState(false);

  const handleSend = async () => {
    await sendMagicLink(email);
    setSent(true);
  };

  if (isAuthenticated) {
    return <p>Logged in! Wallet: {address}</p>;
  }

  if (sent) {
    return <p>Magic link sent! Check your email.</p>;
  }

  return (
    <div>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="your@email.com"
      />
      <button onClick={handleSend}>Send Magic Link</button>
    </div>
  );
}
  1. sendMagicLink(email) sends the email and returns immediately
  2. The SDK starts polling localStorage for the auth result
  3. When the user clicks the link in their email (in any tab or on another device), the result is written to localStorage
  4. Auth state (isAuthenticated, address) updates automatically via onAuthChange

Session Management

Check Authentication State

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

if (isLoading) return <Spinner />;

if (!isAuthenticated) return <LoginButton />;

if (!walletStatus.isReady) {
  return (
    <div>
      {walletStatus.isDeploying && <p>Deploying wallet...</p>}
      {walletStatus.isRegistering && <p>Registering session...</p>}
    </div>
  );
}

// Fully ready
return <App address={address} />;

Logout

const { logout } = useCavos();

async function handleLogout() {
  await logout();
  // isAuthenticated becomes false, address becomes null
}

Session Restoration

The SDK automatically restores sessions on page load via init(). If a valid session exists in browser storage, the wallet is restored without requiring the user to log in again.

Error Handling

JwtExpiredError

When the OAuth JWT has expired (typically after 1 hour), execute() throws a JwtExpiredError. The user must re-login.
import { JwtExpiredError } from '@cavos/react';

try {
  await execute(calls);
} catch (error) {
  if (error instanceof JwtExpiredError) {
    // Prompt user to re-authenticate
    await login('google');
  }
}