Expand description
grab auth login: a real phone login on weblogin.grab.com, driven over
CDP inside an isolated browser context.
grabcli does not replay or forge the login page’s anti-bot tokens
(reCAPTCHA Enterprise, the x-hydraweb-jwt fingerprint). Instead it opens
food.grab.com/auth/login in a fresh Target.createBrowserContext
context (own cookie jar, shared with no other tab, so nothing else in the
browser can log it out) and lets the real page do its own checks, the way
a person would. grabcli only:
- types the phone number and keeps “Remember me … 60 days” ticked;
- clicks Continue and, if Grab offers a choice, picks ONE challenge (in-app approval or OTP) — this is the only step that sends anything;
- later (same or another process) types the OTP, or waits for the in-app approval;
- lets the page redirect through
food.grab.com/auth/callbackinside the context, reads the context’s cookies withStorage.getCookies, saves them as the session and disposes the context.
The context outlives the process (disposeOnDetach: false); what’s needed
to resume (context/tab ids, expiry, the masked phone) is the
PendingLogin value, which the caller keeps (the CLI in a 0600 file, a
daemon in memory). The step functions take it as &mut Option<_> and set
it to None once the login is over (logged in, or ended for good). Sends
are rate-limited by an injectable SendBudget and never retried.
This module writes no files and logs nothing: it never prints cookie
values, tokens, OTPs or the full phone number. LoginDriver wraps the
steps as a small state machine for daemons (one driver per login, driven
from a thread via block_on or from a task).
Structs§
- Login
Driver - A phone login as a state machine, for a daemon:
startsends ONE challenge (after the injectedSendBudgetallows it), thensubmit_codeorpolluntil the state is terminal, orcancel. Writes no files and logs nothing. The isolated browser context is disposed when the login ends; callcancelwhen abandoning a driver so it is disposed promptly (an abandoned one is otherwise only cleaned up by the browser). - Login
Request - What to start a
LoginDriverwith. - Memory
Send Budget - A
SendLogheld in memory. - Pending
Login - State kept between
--phone …and--otp/--poll. No secrets: ids of the isolated context/tab in the browser and a masked phone. - SendLog
- Timestamps of challenge sends, kept separately from the pending login so
cancelling a login never resets the limits. A plain value: persisting it
is up to the
SendBudgetthat holds it. - Start
Opts - Options for
start.
Enums§
- Channel
- Which challenge to ask Grab for.
- Login
State - What a
LoginDriveris waiting for, or how it ended. Carries no phone number or code (only the masked phone) and redacts the session inDebug. - Pending
Kind - What the send produced.
- Screen
- Where the weblogin page is, from
PROBE_JS. - Wait
Outcome - Outcome of
wait_for_approval.
Constants§
- LOGIN_
START_ URL - Where the browser login starts (redirects to weblogin.grab.com).
- MAX_
SENDS_ PER_ HOUR - Maximum challenge sends in any rolling hour.
- PENDING_
TTL_ SECS - How long a started login stays resumable. Grab’s codes live ~5 min.
- PROBE_
JS - Read-only probe of the login tab. Returns structure and fixed UI strings
only; the CLI never prints
text. - SEND_
COOLDOWN_ SECS - Minimum gap between two challenge sends.
Traits§
- Send
Budget - The challenge-send budget (
SEND_COOLDOWN_SECS,MAX_SENDS_PER_HOUR). Injectable so the caller decides its scope and storage: the CLI keeps one per user in a file; a daemon keeps one per org.
Functions§
- cancel
grab auth login --cancel: dispose the isolated context, forget the pending login (clearingslot). Send limits are kept. Returns whether there was one.- check_
no_ pending - Before
start: refuse while an unexpired login is pending; dispose an expired one (and clearslot). - classify_
screen - dry_
run_ plan - What
--phone …would do, without doing it (--dry-run). - finish_
with_ otp grab auth login --otp <code>: type the code into the waiting page.previs the session to build on (its preference cookies are kept); pass&Session::default()for none. On success (and on a terminal failure)slotis cleared; a rejected code leaves it for another try.- mask_
phone +63••••••••12: the country code and the last two digits only.- order_
tracking_ tabs - food.grab.com tabs in the shared browser that poll order tracking. When
the browser’s food session lapses, such a tab gets 401s from
/trackand the page then calls GrabIDoauth2/logout+ food/auth/logout(every ~16 s), which logs the browser out again right after any login there. The isolated login context is immune, but these tabs still breakgrab auth importand normal browsing. grabcli never closes them. - pending_
json - stdout document after
--phone(or a--pollthat is still waiting). - pick_
option - Pick the challenge option to click for
channel, if Grab offers one. - shared_
browser_ tabs - Order-tracking tabs in the shared browser (best-effort; empty if the
browser is unreachable).
/jsoncan still list a tab for a moment after it was closed, so a non-empty answer is re-checked once after a short delay and only tabs seen both times are reported. - split_
phone - Split
+<cc><national>into (cc, national digits). Spaces, dashes, dots and parentheses are ignored; a trunk0is dropped. - start
- Start a login and send exactly ONE challenge. The caller has already
decided a send is wanted, that silent refresh failed, and that no other
login is pending (see
check_no_pending). Returns the pending login to keep forfinish_with_otp/wait_for_approval. - still_
open - Tabs present in both listings.
- tracking_
tab_ warning - wait_
for_ approval grab auth login --poll: wait up totimeoutfor the in-app approval. Sameslot/prevrules asfinish_with_otp.