Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/shadownrx/apisquare/llms.txt

Use this file to discover all available pages before exploring further.

ApiSquare’s admin panel uses a straightforward username-and-password authentication model. When valid credentials are submitted to POST /api/admin/login, the server generates a cryptographically random 64-character session token, stores it in Vercel KV with a 7-day TTL, and delivers it to the browser as an HTTP-only admin_session cookie. Every subsequent request to a protected admin endpoint is validated by reading that cookie and checking it against KV (or an in-memory store in local development).

Setting credentials

Credentials are supplied via environment variables:
VariableDefaultDescription
ADMIN_USERNAMEadminThe login username
ADMIN_PASSWORD(required)Plaintext password or a bcrypt hash starting with $2b$ / $2a$

Generating a bcrypt hash

Storing a bcrypt hash instead of a plaintext password is strongly recommended for production. Use the included helper script:
node scripts/generate-hash.js mysecretpassword
The script outputs the hash and a ready-to-paste .env line:
✅ Hash generado:

$2b$10$...

Copia esta línea en tu .env:

ADMIN_PASSWORD=$2b$10$...
Copy the ADMIN_PASSWORD=... line into your .env.local (development) or into the Vercel project environment variables (production). At login time, verifyCredentials() detects whether the stored value begins with $2b$ or $2a$ and uses bcrypt.compare() accordingly. Plaintext values are compared with strict equality.

Login flow

1

Navigate to /login

Open the login page at /login in your browser. Enter your admin username and password in the form.
2

Credentials are verified

The form submits to POST /api/admin/login. The server checks the IP’s rate-limit state, then verifies the username against ADMIN_USERNAME and the password against ADMIN_PASSWORD (plaintext or bcrypt).
3

Session cookie is set

On success, the server generates a 32-byte random token (crypto.randomBytes(32).toString('hex')), sets it as the admin_session cookie with the following attributes, and redirects to /admin:
AttributeValue
httpOnlytrue
maxAge604800 (7 days)
sameSitestrict
securetrue in production, false in development
path/
4

Token is persisted in Vercel KV

The token is stored under the key session:{token} with a 7-day TTL:
SET session:<token> "1" EX 604800
In local development without KV configured, the token is added to a Node.js global Set (globalSessions) instead.

Brute-force protection

The login endpoint tracks failed attempts per IP address. Both the attempt counter and the lockout state are stored in Vercel KV when available, or in a Node.js in-process Map (localAttempts) during local development.
ParameterValue
Maximum failed attempts5
Lockout duration15 minutes (900 seconds)
KV key patternratelimit:login:{ip}
After a failed attempt, the 401 response includes the number of attempts remaining before lockout:
{
  "error": "Credenciales incorrectas",
  "remaining": 3,
  "blocked": false
}
Once the 5th failure is recorded, all subsequent login requests from that IP return HTTP 429 until the window expires. The error message is dynamic — the number of minutes remaining is computed at response time and pluralised accordingly:
{
  "error": "Demasiados intentos fallidos. Intentá nuevamente en 15 minutos.",
  "blocked": true,
  "resetIn": 900
}
A successful login clears the rate-limit record for that IP immediately.

Session validation

Every protected admin endpoint calls isAuthenticated() from lib/auth.ts before processing the request. The function follows this precedence:
  1. Read the admin_session cookie from the incoming request.
  2. If the token is present in the in-memory globalSessions set (local dev), return true.
  3. If Vercel KV credentials (KV_REST_API_URL and KV_REST_API_TOKEN) are set, look up session:{token} in KV. Return true only if the stored value equals "1".
  4. As a development fallback (no KV, no in-memory match), return true if the token is exactly 64 characters long.
If the cookie is missing or the token cannot be validated, isAuthenticated() returns false and the endpoint responds with HTTP 401.

Logout

Send a POST request to /api/admin/logout (the “Cerrar sesión” button in the dashboard header does this automatically). The endpoint:
  1. Reads the admin_session cookie value.
  2. Deletes session:{token} from Vercel KV.
  3. Calls removeLocalSession(token) to purge the token from the in-memory set.
  4. Deletes the admin_session cookie (and the legacy admin_authenticated cookie for backwards compatibility).
  5. Redirects the browser to /login.
In local development without KV configured, sessions are stored in Node.js process memory and are lost on every server restart. Always set ADMIN_PASSWORD in .env.local before testing so you can log back in after a restart.

Build docs developers (and LLMs) love