Authentication
Arenaton authenticates users by wallet signature, not username/password. The user signs a one-time challenge with their EOA; the server returns a short-lived bearer token. No custody, no approvals, no signing power transfers to Arenaton.
- Client requests a nonce for the user’s wallet.
- Client signs the canonical sign-in message via
personal_sign. - Client posts the signature to
/api/auth/loginand receives an opaque token. - Client sends
Authorization: Bearer <token>on protected routes.
Endpoints
Section titled “Endpoints”GET /api/auth/nonce
Section titled “GET /api/auth/nonce”Issues a single-use nonce bound to a wallet address.
Query parameters:
| Name | Required | Description |
|---|---|---|
| wallet | yes | EVM address (0x-prefixed, 40 hex). |
Response:
{ "status": "success", "data": { "nonce": "deadbeefdeadbeefdeadbeefdeadbeef", "wallet": "0xabC...123", "expiresAt": "2026-05-07T12:34:56.789Z" }}The nonce is valid for 5 minutes and may only be consumed once.
POST /api/auth/login
Section titled “POST /api/auth/login”Verifies the EIP-191 signature over the canonical sign-in message and issues a bearer token.
Request:
{ "wallet": "0xabC...123", "nonce": "deadbeefdeadbeefdeadbeefdeadbeef", "issuedAt": "2026-05-07T12:30:00Z", "expiresAt": "2026-05-07T12:35:00Z", "signature": "0x<65-byte hex>"}Response:
{ "status": "success", "data": { "token": "<64-char hex>", "wallet": "0xabC...123", "issuedAt": "2026-05-07T12:30:01.000Z", "expiresAt": "2026-05-08T12:30:01.000Z" }}The nonce is consumed atomically on success. A reused nonce returns 401.
GET /api/auth/me
Section titled “GET /api/auth/me”Returns the authenticated wallet for the bearer token.
Header:
Authorization: Bearer <token>Response:
{ "status": "success", "data": { "wallet": "0xabC...123" } }Missing or expired tokens return 401.
Sign-in message
Section titled “Sign-in message”The wallet must sign exactly this UTF-8 message via personal_sign. Bytes must match server-side or verification fails.
Arenaton Sign-InDomain: arenaton.comWallet: <checksummed wallet>Nonce: <nonce>IssuedAt: <RFC3339 UTC>ExpiresAt: <RFC3339 UTC>Statement: Sign in to Arenaton. This signature does not authorize any transaction or transfer.IssuedAt and ExpiresAt are bound into the signature; the server rejects mismatches and time-travel windows (expiresAt < issuedAt, future-dated issuedAt, or windows wider than the nonce TTL).
Token semantics
Section titled “Token semantics”| Property | Value |
|---|---|
| Token format | 32 random bytes, 64 hex chars (lowercase) |
| Server-side storage | SHA-256 hash only — raw token never persisted |
| Session lifetime | 24 hours |
| Nonce lifetime | 5 minutes |
| Nonce reuse | Rejected (single-use) |
| Concurrent sessions | Allowed; each login mints a fresh token |
| Revocation | None in this version (tokens expire on their own) |
Error codes
Section titled “Error codes”| HTTP | code | Meaning |
|---|---|---|
| 400 | auth_invalid_wallet | Wallet missing or not a valid EVM address. |
| 400 | auth_invalid_json | Login body is not valid JSON or has unknown fields. |
| 400 | auth_missing_fields | Nonce or signature is empty after trim. |
| 400 | auth_invalid_issued_at | issuedAt is not RFC3339. |
| 400 | auth_invalid_expires_at | expiresAt is not RFC3339. |
| 400 | auth_invalid_window | Window is reversed, in the past, or too wide. |
| 401 | auth_invalid_signature | Signature does not recover the claimed wallet. |
| 401 | auth_nonce_invalid | Nonce missing, expired, used, or wrong wallet. |
| 401 | auth_missing_bearer | Authorization: Bearer … header missing or empty. |
| 401 | auth_invalid_session | Bearer token unknown or session expired. |
| 500 | auth_nonce_failed | Nonce generation or persistence failure. |
| 500 | auth_session_failed | Session generation or persistence failure. |
| 500 | auth_lookup_failed | Session lookup failure. |
| 503 | database_unavailable | Server cannot reach the database. |
Boundaries
Section titled “Boundaries”- Arenaton never holds private keys, mnemonics, or session-signing power.
- The sign-in message explicitly states it does not authorize any transaction or transfer.
- No spender approvals, no on-chain transactions, no custody surfaces are touched by sign-in.
- Tokens are stored as SHA-256 hashes; database compromise does not expose live tokens.
- Session lookup is by hash, not by raw token, so timing analysis is not exploitable.
Limitations
Section titled “Limitations”- EOA wallets only. Smart-account (EIP-1271) verification is not supported in this version.
- No
/api/auth/logoutendpoint. Sessions can only be invalidated by waiting for expiry. - No automatic refresh. Clients should treat 401 as “sign in again” and not retry silently.