By patrick

DocView Authentication Process

By patrick · Created Feb 24, 2026 public

DocView uses Better Auth with magic link email authentication, plus a device-code flow for CLI clients.

Overview

flowchart TD
    Client[Client Request] --> SessionMW[Session Middleware]
    SessionMW -->|Cookie present| BetterAuth[Better Auth getSession]
    SessionMW -->|Bearer token| DBLookup[Direct DB session lookup]
    SessionMW -->|Neither| Unauthed[Continue unauthenticated]
    BetterAuth -->|Valid| Authed[req.userId + req.userEmail set]
    DBLookup -->|Valid token| Authed
    Authed --> Routes[Route handlers]
    Unauthed --> Routes

1. Magic Link Flow (Browser)

The primary auth method — passwordless email login via Better Auth's magic link plugin.

sequenceDiagram
    participant U as User
    participant B as Browser
    participant S as DocView Server
    participant BA as Better Auth
    participant E as Resend (Email)

    U->>B: Enters email on login page
    B->>S: POST /api/auth/magic-link
    S->>BA: magicLink plugin
    BA->>E: Send email with signed URL
    E->>U: Email with magic link
    U->>B: Clicks magic link
    B->>S: GET /api/auth/magic-link/verify?token=...
    S->>BA: Verify token, create session
    BA->>B: Set session cookie
    Note over B: better-auth.session_token cookie set

Key details:

2. Device Code Flow (CLI)

An OAuth2-style device authorization flow that lets CLI tools authenticate by having the user approve a code in their browser.

sequenceDiagram
    participant CLI as CLI Tool
    participant S as DocView Server
    participant B as User's Browser

    CLI->>S: POST /api/device-code
    S-->>CLI: { code: "a1b2c3d4", verification_url, expires_in: 1800 }
    Note over CLI: Display code + URL to user

    loop Poll every few seconds
        CLI->>S: GET /api/device-code/a1b2c3d4
        S-->>CLI: { status: "pending" }
    end

    Note over B: User opens verification_url
    B->>S: POST /api/device-code/approve (with session cookie + code)
    Note over S: Extracts raw session cookie value<br/>Stores in device_codes table

    CLI->>S: GET /api/device-code/a1b2c3d4
    S-->>CLI: { status: "approved", session_token: "better-auth.session_token=..." }
    Note over CLI: Store token for future Bearer auth
    Note over S: Device code row deleted after retrieval

Key details:

3. Session Resolution Middleware

Every request passes through a global middleware (server.js:16-55) that resolves the user identity:

flowchart TD
    Req[Incoming Request] --> TryCookie{Has session cookie?}
    TryCookie -->|Yes| GetSession[auth.api.getSession<br/>via Better Auth]
    GetSession -->|Valid| SetUser[Set req.userId + req.userEmail]
    GetSession -->|Invalid| CheckBearer
    TryCookie -->|No| CheckBearer{Has Authorization:<br/>Bearer header?}
    CheckBearer -->|Yes| DBQuery[Query session table<br/>WHERE token = ? AND not expired]
    DBQuery -->|Found| SetUser
    DBQuery -->|Not found| NoAuth[Continue unauthenticated]
    CheckBearer -->|No| NoAuth
    SetUser --> Next[next]
    NoAuth --> Next

Two auth paths, unified result:

Method Source Used By
Cookie better-auth.session_token cookie Browser sessions
Bearer Authorization: Bearer <token> CLI (from device flow)

4. Route-Level Authorization

Routes use two middleware helpers from routes/api.js:

5. Document Visibility

Documents have a visibility field (public or private):