Authentication

Set up user authentication with email/password, magic links, OAuth, API keys, and two-factor auth.

#Authentication

EmuView handles user identity and session management using Better Auth, running natively on Cloudflare Workers. You get multiple authentication methods out of the box — no backend code to write.

#What you can do

Method Description Setup required
Email + password Traditional sign-up and sign-in with PBKDF2 hashing None (built-in)
Username + password Sign in by username; email optional at signup Enable in Settings → Authentication (guide)
Magic links Passwordless login via email links Cloudflare Email Routing
Google OAuth Sign in with Google accounts Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET env vars
GitHub OAuth Sign in with GitHub accounts Set GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET env vars
API keys Server-side admin access with sk- prefixed tokens None (built-in)
Two-factor (TOTP) Time-based one-time passwords via authenticator apps None (built-in plugin)

#Key concepts

Concept What it means
Session token An opaque token from Better Auth, sent as Authorization: Bearer <token>. Managed automatically by the SDK
API key A sk- prefixed key for server-side access. Stored as a SHA-256 hash in D1. Capabilities can be scoped per key
Role One of 6 built-in roles assigned to each user: super_admin, admin, editor, viewer, api, public
Signup mode Controls registration: open (anyone can register), invite (admin creates accounts), disabled (setup script only)

#How it fits together

Authentication feeds into access control. When a request arrives:

  1. The auth middleware resolves the session or API key to a user identity
  2. The user's role determines their base permissions
  3. Per-collection access policies further restrict read/write/delete operations
  4. Row-level and column-level security filters the response

Here is the full journey from sign-in to an authorized API call:

sequenceDiagram
    participant App as Your app
    participant GW as Gateway Worker
    participant BA as Better Auth
    participant KV as Session cache (KV)

    App->>GW: POST /api/auth/sign-in/email
    GW->>BA: Verify credentials against D1
    BA-->>App: Session token
    App->>GW: GET /api/v1/... with Bearer token
    GW->>KV: Look up hashed token
    alt Cache miss
        GW->>BA: Verify session
        GW->>KV: Cache user (5 min TTL)
    end
    GW-->>App: Response filtered by role and access policies

The gateway hashes the token before using it as a cache key, so raw tokens never appear in KV. Revoking a user or changing their role invalidates the cached entry immediately.

Warning

Never embed admin API keys in client-side code. Anyone can read them from browser developer tools. Use session tokens from auth.signIn() for frontend apps.

#Guides in this section

  • Email and password — Set up traditional registration and login
  • Username sign-in & optional email — Usernames as login identifiers, no-email accounts, shared-email recovery
  • Magic links — Configure passwordless email authentication
  • OAuth providers — Connect Google and GitHub sign-in
  • API keys — Create and manage server-side access tokens
  • Two-factor authentication — Add TOTP-based second factor