Protect Your Endpoints
Add authentication to your API endpoints with JWT tokens and role-based access.
Protect Your Endpoints
Not every endpoint should be public. You can require authentication so only logged-in users (or users with specific roles) can access certain routes.
The endpoint editor with the JWT authentication option Enable JWT authentication on any endpoint
Require authentication
Open the endpoint
Go to Endpoints and click the endpoint you want to protect.
Set authentication to JWT
In the endpoint editor, change Authentication from None to JWT.
Save
Click Save. The endpoint now requires a valid token in the Authorization header.
Clients must include the token like this:
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
If the token is missing or invalid, Spala returns a 401 Unauthorized response automatically.
How JWT tokens work
JWT (JSON Web Tokens) is a simple way to handle login sessions:
1. A user logs in with their email and password via a public /api/auth/login endpoint 2. Your login function verifies the credentials and creates a token using a Generate Auth Token step 3. The client stores the token and sends it with every request 4. Protected endpoints automatically verify the token before running the function
Good to know
Tokens contain user data (like id, email, role) and expire after a set time (e.g., 24 hours). No database lookup is needed to verify them.
Frontend session contract
Frontend builders need the exact session contract generated for the project. At handoff time, document:
| Field | Example | | --- | --- | | Login route | POST /api/auth/login | | Signup route | POST /api/auth/register | | Token field | token, accessToken, or data.token | | Protected header | Authorization: Bearer USER_JWT | | Expiry | 24h, 7d, or project-specific | | Refresh route | POST /api/auth/refresh, if implemented | | Logout behavior | Clear local token, revoke server session, or both | | Cookie mode | credentials: "include" if the project uses cookie sessions | | CSRF header | Required only when the project implements CSRF protection |
If no refresh route is documented, treat token expiry as a login-required event. If the project uses cookie sessions, browser CORS must also allow credentials and the frontend must use credentials: "include".
Cookie-session request example:
const response = await fetch(`${SPALA_API_BASE_URL}/api/me`, {
credentials: "include",
headers: {
"X-CSRF-Token": csrfToken,
},
});
The CSRF header name, cookie attributes, same-site policy, and logout behavior are project-specific. Document them in the generated API docs or frontend handoff packet before asking an external frontend developer to integrate cookie auth.
Cookie checklist for browser clients:
| Field | What to confirm | | --- | --- | | SameSite | Lax, Strict, or None; cross-site cookies require SameSite=None | | Secure | Required for cross-site HTTPS cookies | | Domain/path | Which frontend and API hosts receive the cookie | | CSRF source | Meta tag, cookie, endpoint, or generated page value | | Logout | Whether logout expires the cookie, revokes the server session, or both |
Built-in endpoint auth vs manual verification
Use endpoint-level JWT authentication when an endpoint should be protected before its function runs. This is the usual production path for user-facing APIs because Spala rejects missing or invalid tokens automatically and exposes decoded auth data to the function.
Use a manual Verify JWT step inside a function only when the endpoint intentionally accepts mixed public/authenticated traffic, needs to verify a secondary token, or is implementing a custom auth handshake such as a realtime connection or webhook signature.
Access the logged-in user in a function
When an endpoint has JWT authentication enabled, the decoded token data is available in your function:
vars.auth.userId // The user's ID vars.auth.email // The user's email vars.auth.role // The user's role, such as "admin" or "user"
Use this to personalize responses or restrict actions:
// Only return the current user's cases Database Query: SELECT * FROM cases WHERE client_id = vars.auth.userId
Add role-based access
For admin-only endpoints, add a role check at the start of your function:
// Step 1: Check role
If/Else: vars.auth.role !== 'admin'
True branch: Return { error: "Admin access required" }, Status: 403
// Step 2: Continue with admin logic...
Which endpoints to protect?
| Endpoint | Auth | Why | |----------------------|--------|----------------------------------| | POST /api/auth/login | None | Users need to log in | | POST /api/auth/register| None | Users need to sign up | | GET /products | None | Anyone can browse | | POST /products | JWT | Only logged-in users can create | | DELETE /products/:id| JWT | Only admins can delete | | GET /orders | JWT | Users see only their own orders |
Never store plain-text passwords
Always use the Hash Password step (bcrypt) before saving passwords, and Verify Password when verifying during login.
Create an Endpoint /endpoints/creating-endpoints Set up endpoints step by step Inputs & Outputs /endpoints/inputs-outputs Handle request data User Authentication Guide /guides/user-auth Full login and registration setup