Wallet sign-in
Sign-In with Ethereum. The wallet is the account — there is no user table.
Signing in proves you control an address. It authorises no transaction, moves no funds and costs no gas. What you get back is a session cookie, which is a receipt for that proof and nothing else.
Wallet discovery
Wallets are enumerated over EIP-6963 rather than read off window.ethereum. The old approach breaks the moment two wallets are installed: whichever extension injected last wins and the user has no say. EIP-6963 has every wallet announce itself, so the app can list them and let you pick.
Robinhood Wallet is listed first, because Crifine's RWA coverage is built around Robinhood Chain. Nothing is exclusive to it — any EIP-1193 wallet signs in, and a wallet that predates EIP-6963 falls back to the injected provider.
On a phone
Sign-in works in a wallet's own in-app browser — MetaMask Mobile, Coinbase Wallet, Trust. Those inject window.ethereum directly, and some do not announce over EIP-6963 at all, so the app watches for the injected provider rather than checking once: on mobile the page can start running before the wallet has finished installing it, and a single check would report "no wallet" from inside a wallet.
The flow
- 1
Challenge
POST /api/auth/challengemints a nonce, binds it to the requesting address in a signed cookie, and returns the exact EIP-4361 message to sign. - 2
Sign
The wallet signs that message with
personal_sign. Nothing is broadcast. - 3
Verify
POST /api/auth/verifychecks the nonce, the domain, the expiry and the recovered address, then sets an HMAC-signed session cookie.
dapp.crifine.app wants you to sign in with your Ethereum account:
0x70997970C51812dc3A010C7d01b50e0d17dc79C8
Sign in to Crifine. This signature proves you control this wallet. It
authorises no transaction and moves no funds.
URI: https://dapp.crifine.app
Version: 1
Chain ID: 1
Nonce: t_wDAvxX_g9NUYrYPpaVKw
Issued At: 2026-09-01T15:50:32.909Z
Expiration Time: 2026-09-01T16:00:32.909ZA known limit on the nonce
A cookie cannot be invalidated server-side, so the nonce is single-use only for a client that honours the clearing Set-Cookie. A caller with its own cookie jar can replay the same message, signature and nonce cookie until the ten-minute expiry — and would sign in as the address that actually signed, no other.
Closing that window properly needs server-side storage: a KV namespace with the nonce key deleted on first use. That is the intended production step and it is documented here rather than left for someone to discover.