Skip to content

How It Works

SaeedX edited this page Jun 25, 2026 · 1 revision

How It Works

The API reproduces the same login handshake the Free Fire client performs against Garena, then returns the resulting session token as JSON.

High‑level flow

                  ┌──────────────────────────────────────────────┐
  GET /v1/auth ──►│ 1. Validate API key (master key or DB lookup) │
                  └───────────────────────┬──────────────────────┘
                                          ▼
        ┌───────────────────────────────────────────────────────────┐
        │ 2. Garena OAuth guest token grant                          │
        │    POST 100067.connect.garena.com/oauth/guest/token/grant  │
        │    → access_token, open_id                                 │
        └───────────────────────────┬───────────────────────────────┘
                                    ▼
        ┌───────────────────────────────────────────────────────────┐
        │ 3. Build Protobuf LoginReq(open_id, login_token=access)    │
        │    → serialize → AES‑128‑CBC encrypt                       │
        └───────────────────────────┬───────────────────────────────┘
                                    ▼
        ┌───────────────────────────────────────────────────────────┐
        │ 4. POST encrypted payload to {MAJOR_LOGIN_URL}/MajorLogin  │
        │    headers include ReleaseVersion, octet-stream body       │
        └───────────────────────────┬───────────────────────────────┘
                                    ▼
        ┌───────────────────────────────────────────────────────────┐
        │ 5. Parse Protobuf LoginRes → JSON → reorder + clean        │
        └───────────────────────────┬───────────────────────────────┘
                                    ▼
                            JSON response to client

Step 1 — API‑key validation

The incoming apikey is accepted if it equals the master VALID_API_KEY, or if it exists in the api_keys table with status='active' and an expires_at in the future. See API Reference.

Step 2 — Garena OAuth guest token grant

A form‑encoded POST is sent to:

https://100067.connect.garena.com/oauth/guest/token/grant

with the guest uid + password, a fixed client_id / client_secret, response_type=token and client_type=2. The response yields:

  • access_token
  • open_id

These identify the guest session for the next step.

Step 3 — Build & encrypt the Protobuf LoginReq

A LoginReq Protobuf message is populated:

Field Value
open_id from step 2
open_id_type "4"
login_token the access_token from step 2
orign_platform_type "4"

The serialized message is padded (PKCS‑style) and encrypted with AES‑128 in CBC mode using the built‑in MAIN_KEY / MAIN_IV.

Step 4 — Call MajorLogin

The encrypted bytes are sent as application/octet-stream to {MAJOR_LOGIN_URL}/MajorLogin with headers including:

Header Value
User-Agent Android Dalvik UA string
Content-Type application/octet-stream
X-Unity-Version 2018.4.11f1
X-GA v1 1
ReleaseVersion from config.json (e.g. OB53)

MAJOR_LOGIN_URL and ReleaseVersion come from the remote config.json, so they can be updated as the game changes without a code change.

Step 5 — Parse LoginRes

The binary response is parsed back into the LoginRes Protobuf message and converted to JSON. The app:

  • removes ttl and anoUrl,
  • re‑orders the remaining fields into a stable shape,
  • injects the accessToken from step 2,

then returns the final JSON described in API Reference.

The Protobuf schema

The .proto definitions are embedded directly in app.py as a serialized descriptor. The relevant messages are:

  • LoginReqopen_id, open_id_type, login_token, orign_platform_type
  • LoginResaccount_id, region fields, token, server_url, blacklist (ban info), queue_info, and more
  • BlacklistInfoRes + BanReason enum — used for ban/blacklist details

Concurrency

The handshake (get_jwt) is fully async (httpx.AsyncClient) and run per‑request via asyncio.run. In production, Gunicorn's gevent workers handle many concurrent connections — see Deployment.