Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/PloutusLab/krafta-web/llms.txt

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

Krafta handles identity with a custom HMAC-SHA256 JWT implementation that runs entirely in Next.js Route Handlers — no third-party auth library is required. Every successful authentication call sets a krafta-token HttpOnly cookie that the browser sends automatically on subsequent requests. Passwords are hashed with PBKDF2-SHA512 before storage.

POST /api/auth/register

Creates a new user account with the default CLIENTE role, signs a JWT, and sets the session cookies immediately so the user is logged in upon registration.

Request body

email
string
required
The user’s email address. Stored in lowercase. Must not already be registered in the system.
password
string
required
Plain-text password. Must be at least 6 characters long. Hashed with PBKDF2-SHA512 before storage; never persisted in plain text.

Response

success
boolean
Always true on a 200 response.
user
object
The newly created user object.
{
  "success": true,
  "user": {
    "id": "a1b2c3d4-...",
    "email": "usuario@example.com",
    "role": "CLIENTE",
    "creatorStore": null
  }
}

Cookies set

CookieValueFlags
krafta-tokenSigned JWTHttpOnly, SameSite=lax, Secure (prod), 24 h
krafta-roleCLIENTESameSite=lax, 24 h

Error responses

StatusCondition
400email or password field is missing from the body
400Email is already registered
400Password is shorter than 6 characters

POST /api/auth/login

Verifies credentials against the stored PBKDF2-SHA512 hash and, on success, signs a new JWT and sets the session cookies.

Request body

email
string
required
The registered email address.
password
string
required
The account password.

Response

success
boolean
true on a successful login.
user
object
The authenticated user object.
{
  "success": true,
  "user": {
    "id": "a1b2c3d4-...",
    "email": "usuario@example.com",
    "role": "CLIENTE",
    "creatorStore": null
  }
}

Cookies set

CookieValueFlags
krafta-tokenSigned JWTHttpOnly, SameSite=lax, Secure (prod), 24 h
krafta-roleUser role stringSameSite=lax, 24 h

Error responses

StatusCondition
400email or password field is missing
401Email not found or password does not match

Example

curl -X POST http://localhost:3000/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email": "admin@example.com", "password": "yourpassword"}' \
  -c cookies.txt

POST /api/auth/logout

Terminates the current session by expiring both auth cookies. No request body is required.

Response

success
boolean
true when the cookies have been cleared.
message
string
Human-readable confirmation: "Sesión cerrada correctamente".
{
  "success": true,
  "message": "Sesión cerrada correctamente"
}
The krafta-token and krafta-role cookies are overwritten with empty values and maxAge: 0, causing browsers to immediately discard them.

GET /api/auth/me

Returns the currently authenticated user’s profile. The endpoint reads the krafta-token cookie, verifies the JWT signature and expiry, and fetches the fresh user record from the database. Unlike the login response, this endpoint performs a live database lookup so that any role changes made since the token was issued are reflected in the response.

Response

authenticated
boolean
true when a valid, unexpired token is present and the user exists.
user
object
Present only when authenticated is true.
{
  "authenticated": true,
  "user": {
    "id": "a1b2c3d4-...",
    "email": "creador@example.com",
    "role": "CREADOR",
    "creatorStore": {
      "displayName": "Estudio Luna",
      "slug": "estudio-luna",
      "bio": "Diseños minimalistas para el día a día."
    }
  }
}
When no valid cookie is present or the token has expired, the endpoint responds with HTTP 200 and { "authenticated": false } rather than a 401, so client-side session checks are always safe to make.

POST /api/auth/convert-creator

Upgrades the authenticated user from CLIENTE to the CREADOR role and creates the associated Creator and CreatorStore records. A new JWT with the updated role is re-issued and set on the response cookies. This endpoint requires a valid krafta-token cookie. Callers that are already CREADOR, ADMIN, or TALLER should not call this endpoint.

Request body

displayName
string
required
The public-facing name of the creator’s store (e.g. "Estudio Luna").
slug
string
required
A URL-friendly handle for the store. Sanitized server-side: lowercased and stripped of characters outside [a-z0-9-_]. Must be unique across all creator stores.
bio
string
A short description of the creator’s store. Optional.

Response

success
boolean
true on a successful conversion.
user
object
Updated user object reflecting the new CREADOR role.
{
  "success": true,
  "user": {
    "id": "a1b2c3d4-...",
    "email": "usuario@example.com",
    "role": "CREADOR",
    "creatorStore": {
      "displayName": "Estudio Luna",
      "slug": "estudio-luna",
      "bio": "Diseños minimalistas para el día a día."
    }
  }
}

Error responses

StatusCondition
400displayName or slug is missing from the request body
400The sanitized slug is already in use by another creator
401No krafta-token cookie present, or the token is expired/invalid

How authentication is enforced

Both cookies are scoped to path: "/" and set with SameSite=lax. The krafta-token cookie carries the HttpOnly flag so JavaScript running in the browser cannot read it. In production (NODE_ENV === "production"), both cookies are also marked Secure, restricting transmission to HTTPS connections only.

JWT structure

Tokens use the HS256 algorithm. The payload contains:
{
  "id": "<user-uuid>",
  "email": "usuario@example.com",
  "role": "CLIENTE",
  "exp": 1720000000
}
The signature is computed with HMAC-SHA256 keyed on the JWT_SECRET environment variable. Tokens expire 24 hours after issuance. There are no refresh tokens; users must re-authenticate once a token expires.

Role-based access control

Server-side route handlers that require a specific role call requireRole(request, ["ADMIN"]) from src/lib/api-auth.js. This helper:
  1. Reads the krafta-token cookie from the incoming request.
  2. Verifies the JWT signature and expiry.
  3. Checks that the decoded role claim is in the list of allowed roles.
  4. Returns a 403 response if the check fails, or the decoded user payload if it passes.
Valid roles defined in the Prisma schema are CLIENTE, ADMIN, TALLER, and CREADOR.

Build docs developers (and LLMs) love