mirror of
https://github.com/Twigpine/openlaunch.git
synced 2026-11-08 08:49:32 -10:00
4.2 KiB
4.2 KiB
Admin sign-in
/admin (reported posts, profiles, season points, the Boosted lane, community pairs) is for the wallets in the
ADMIN_WALLETS secret. Code: app/src/lib/admin/.
Signing in
Without an admin session, /admin is a sign-in card and nothing else: no panel and no admin data is rendered.
- Connect an admin wallet and press Sign in.
- The server issues a nonce (
POST /api/admin/nonce, single use, 5 minutes) with its own time. - The wallet signs a standard Sign-In with Ethereum message (EIP-4361) for
openlaunch.lol, on Base. Wallets that support the standard compare its domain with the site asking for the signature and warn on a mismatch, so a look-alike site cannot quietly collect an openlaunch sign-in. POST /api/admin/sessionaccepts only the exact text the site builds: this domain and URL, Base, the fixed statement, a nonce this server issued, issued within 5 minutes. The signer must be inADMIN_WALLETS. The nonce must be open before the signature is checked (a made-up one costs no RPC) and is spent only after it checks out. Smart wallets are checked on Base.
The session
- An 8-hour session, never extended. A random 32-byte token sits in a
__Host-ol_admincookie: HttpOnly (no page script can read it), Secure, SameSite=Strict, Path=/, no Domain (bound to openlaunch.lol exactly, never basebid.lol). - The database (
bb_admin_sessions) keeps only the token's SHA-256, a rough device label ("Chrome · macOS") and the times. No IP, no user agent. - Every request checks that the session exists, is not ended, has not expired, and that its wallet is still in
ADMIN_WALLETS. A request never ends sessions itself: while a secret change rolls out, a machine still on the old list would end a newly added admin's. Ending a removed wallet's sessions is done at boot (see Ops). - At most 5 sessions per wallet; signing in again ends the oldest.
- Sessions on
/adminlists this wallet's sessions. Each can be ended, or all of them with Sign out everywhere. Sign out ends the session on the server, not only in the browser. - Sign-in, sign-out and every admin action only accept requests from the site's own pages (the Origin header), on top of SameSite=Strict. An action must name the wallet that signed it; one without is refused, never treated as a read. Sign-in is limited to 10 a minute per IP and per wallet.
- Opening
/adminfrom a link on another site sends no Strict cookie on that first load. The card asks the server from inside the page and loads the panels when a session is there, so there is no second signature.
What needs what
| Session | Its own wallet signature | |
|---|---|---|
| The admin page and the admin reads (reported posts, Boost stats, the profile queue, the season boards) | yes | no |
| Every admin action (hide, list, review, season actions, profile moderation) | yes, same wallet | yes, single-use nonce |
| A token's creator muting their own token's thread | no | yes |
A stolen cookie cannot act without the wallet, and a phished action signature cannot act without the cookie.
Ops
- Remove an admin: take the wallet out of
ADMIN_WALLETS(fly secrets set ADMIN_WALLETS=… -a basebid). The secret change restarts the machines, and at boot every session of a wallet no longer listed is ended for good (retried if the database is briefly unreachable): adding the wallet back later revives none of them. Until a machine restarts it still has the old list, so the swap takes as long as the restart (a minute or so). - Add an admin: add the wallet to
ADMIN_WALLETSthe same way, and sign in once both machines have restarted. - Adding back a removed wallet, or if the log shows
[admin] session sweep failed: end that wallet's old sessions first,UPDATE bb_admin_sessions SET revoked_at = now() WHERE wallet = '<address, lowercase>' AND revoked_at IS NULL;(the boot sweep normally did it already; this covers a sweep that failed all its tries). - End every session at once (a lost device):
UPDATE bb_admin_sessions SET revoked_at = now() WHERE revoked_at IS NULL; - Sign-ins and sign-outs are logged as
[admin] signed in: <wallet> (<device>)and[admin] signed out: ….