Files
OpenFlare/docs/en/design/login-captcha.md
T
ryan 454542c1d0 docs(i18n): 恢复并补齐英文版 vitepress,README 默认改为英文
- README 默认英文:README.en.md → README.md(英文为默认),中文移至 README.zh-CN.md,语言切换链接同步
- 恢复被删除的 docs/en/ 英文文档(git 历史 cc5e53c5^),删除 4 篇已废弃文件
- 英文导航 config.ts 对齐中文结构(新增 Deployment/Changelog 侧栏,同步 Guide/Design 条目)
- 翻译 15 篇中文新增文档:guide 5 篇(certificates/pages-usage/proxy-config/uptime-kuma/zone-domain-migration)+ design 10 篇(zone-design/cloudflare-pointing/waf-orchestration/origin-error-page/edge-cache-design/pages-design/logstore/kuma-design/login-captcha/observability 三篇)
- en 首页更新(新增 Pages 特性、tagline 同步);changelog 英文入口指向中文版
- vitepress 构建验证:43 个英文页面全部渲染

注意:29 篇旧英文文档为恢复版,部分内容(如 deployment/server、reference/configuration)可能落后于中文,需后续逐篇同步
2026-08-16 23:18:29 +08:00

5.6 KiB

Login CAPTCHA Integration (Cap)

This document describes the design of introducing Cap — an open-source CAPTCHA solution based on Proof-of-Work (PoW) and invisible browser fingerprint features — into the OpenFlare control plane, to protect the login API against brute-force attacks and credential-stuffing by crawlers.


1. Business Background and Product Scope

Background and Pain Points

The OpenFlare login endpoint /api/v1/user/login lacks user-dimension protection; attackers can use proxy pools to perform credential stuffing and brute-force attacks on high-privilege accounts (such as root). At the same time, standard visual CAPTCHAs are unfriendly to login-page UX and accessibility.

Product Scope and Technology Choice

  • Technology choice: Cap (a Proof-of-Work-driven, invisible, image-free CAPTCHA solution).
    • Core principle: the client (Widget/page) obtains a proof-of-work (PoW) challenge from the server, computes the solution in the browser background, and sends the answer back. The server verifies the answer to complete human-machine verification.
    • Advantages: invisible, image-free, no dependency on external third-party API nodes (private), tiny package size.
  • Integration scope: the control-plane Server login API (/api/v1/user/login) and the frontend login page.
  • Config granularity: admins can toggle the CAPTCHA on/off anytime via the console Option table (cap_login_enabled).

2. System Architecture and Interaction Sequence

2.1 Module Responsibilities

  1. Frontend:
    • Introduces the cap-widget (React 19 custom element) on the login page.
    • On form submit, accompanies the submission with the cap-token solved by the Widget.
  2. Server (control-plane backend):
    • Exposes POST /api/cap/challenge to distribute the PoW challenge and a signed JWT token to the client.
    • Exposes POST /api/cap/redeem to verify the submitted PoW solution and issue a login credential (Redeem Token) with an expiry time.
    • Stores the Redeem Token and its expiry in the in-memory/Redis cache.
    • In POST /api/v1/user/login, when CAPTCHA protection is enabled, first validates and consumes (single-use) the corresponding cap-token.

2.2 Verification Flow Sequence Diagram

sequenceDiagram
    autonumber
    actor User as User
    participant Browser as Browser (Frontend Web)
    participant Server as OpenFlare Server (Backend)
    participant Cache as Memory/Redis Cache

    User->>Browser: Open login page
    Browser->>Server: POST /api/cap/challenge (get challenge)
    Server->>Browser: Return {challenge, token, expires} (JWT format)
    Note over Browser: Widget computes the PoW challenge in background (WASM/Worker)
    Browser->>Server: POST /api/cap/redeem (submit solutions + token)
    alt PoW solution valid
        Server->>Cache: Store Redeem Token (tokenKey:expires)
        Server->>Browser: Return {success: true, token} (i.e. cap-token)
    else validation failed
        Server->>Browser: Return {success: false, reason}
    end
    User->>Browser: Enter account/password, click login
    Browser->>Server: POST /api/v1/user/login (with X-Cap-Token in HTTP header)
    alt CapLoginEnabled = true
        Server->>Server: Middleware (CapAuth) validates and consumes X-Cap-Token
        alt token valid, not expired, not consumed
            Server->>Server: c.Next() -> normal login logic (Bcrypt password check)
            Server->>Browser: Return login success (Session Cookie)
        else token invalid or already consumed
            Server->>Browser: Intercept and return CAPTCHA error (401 Unauthorized)
        end
    else CapLoginEnabled = false
        Server->>Server: c.Next() -> normal login logic
    end

3. Core APIs and Data Model

3.1 API Definitions

1. Get Challenge (POST /api/cap/challenge)

  • Method: POST
  • Auth: public
  • Response payload (unified API envelope, data is the business payload):
    {
      "error_msg": "",
      "data": {
        "challenge": {
          "c": 1,
          "s": 32,
          "d": 4
        },
        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
        "expires": 1717660800000
      }
    }
    

2. Redeem Challenge (POST /api/cap/redeem)

  • Method: POST
  • Request payload:
    {
      "token": "challenge_jwt_token_here",
      "solutions": [12345, 67890, 54321]
    }
    
  • Response payload (success):
    {
      "success": true,
      "token": "random_id:ver_token",
      "expires": 1717661000000
    }
    

3. Login API (POST /api/v1/user/login)

  • Request payload unchanged:
    {
      "username": "root",
      "password": "your_password"
    }
    
  • CAPTCHA carrier: placed in the HTTP Request Header X-Cap-Token.

4. Replay Attack Protection and Security Trade-offs

  1. JWT temporary state binding: the challenge is signed into the JWT payload at generation time, including an expiry limit (10 minutes).
  2. Replay interception (nonce consumption): when the client calls /redeem to submit the solution, the backend marks the JWT signature as used in the cache. Re-submitting the same solution package returns already_redeemed.
  3. Redeem single-use (one-time invalidation): when the client logs in and submits the cap-token, the backend immediately deletes the key from the cache after validating it, preventing attackers from extracting historical valid cap-tokens for login replay.
  4. Seamless verification: by tuning parameters like c (challenge count) and d (difficulty), you balance solve time against anti-crawler strength; users solve silently in the background without interrupting the login flow.