ApiSquare’s admin panel uses a straightforward username-and-password authentication model. When valid credentials are submitted toDocumentation 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.
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:| Variable | Default | Description |
|---|---|---|
ADMIN_USERNAME | admin | The 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:.env line:
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
Navigate to /login
Open the login page at
/login in your browser. Enter your admin username and password in the form.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).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:| Attribute | Value |
|---|---|
httpOnly | true |
maxAge | 604800 (7 days) |
sameSite | strict |
secure | true in production, false in development |
path | / |
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-processMap (localAttempts) during local development.
| Parameter | Value |
|---|---|
| Maximum failed attempts | 5 |
| Lockout duration | 15 minutes (900 seconds) |
| KV key pattern | ratelimit:login:{ip} |
401 response includes the number of attempts remaining before lockout:
429 until the window expires. The error message is dynamic — the number of minutes remaining is computed at response time and pluralised accordingly:
Session validation
Every protected admin endpoint callsisAuthenticated() from lib/auth.ts before processing the request. The function follows this precedence:
- Read the
admin_sessioncookie from the incoming request. - If the token is present in the in-memory
globalSessionsset (local dev), returntrue. - If Vercel KV credentials (
KV_REST_API_URLandKV_REST_API_TOKEN) are set, look upsession:{token}in KV. Returntrueonly if the stored value equals"1". - As a development fallback (no KV, no in-memory match), return
trueif the token is exactly 64 characters long.
isAuthenticated() returns false and the endpoint responds with HTTP 401.
Logout
Send aPOST request to /api/admin/logout (the “Cerrar sesión” button in the dashboard header does this automatically). The endpoint:
- Reads the
admin_sessioncookie value. - Deletes
session:{token}from Vercel KV. - Calls
removeLocalSession(token)to purge the token from the in-memory set. - Deletes the
admin_sessioncookie (and the legacyadmin_authenticatedcookie for backwards compatibility). - Redirects the browser to
/login.