Skip to content
Hoody.com

Hoody Exec’s @token magic comment adds shared-secret authentication to any script, covering both HTTP requests and WebSocket connections. You do not add middleware, an auth library, or JWT infrastructure.

// @token my-secret-key-123
return { data: 'only authenticated requests see this' };

Unauthenticated requests get 401 Unauthorized. Authenticated requests run your script normally.


  1. You add // @token <secret> at the top of your script.
  2. The server checks every incoming request for a matching token before your code runs.
  3. A matching token lets the script execute normally.
  4. A missing or wrong token returns 401 Unauthorized, and your code never runs.

The token check happens at the server level, before VM creation and metadata construction. There is no way for a script to see or override the gate.


A client can send the token four ways. The server checks them in the order below and uses the first one present.

PriorityMethodHeader / Parameter
1aBearer tokenAuthorization: Bearer <token>
1bBasic auth (password field)Authorization: Basic base64(user:token)
2X-Token headerX-Token: <token>
3Query parameter?token=<token>

If multiple sources are present, only the highest-priority one is used. For example, if both Authorization: Bearer and X-Token are sent, only the Bearer value is checked.


Bearer is the standard approach for API clients and SDKs.

Terminal window
curl -H "Authorization: Bearer my-secret-key-123" \
"https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/api/data"

The scheme name is case-insensitive (Bearer, bearer, BEARER all work).


The server matches the @token value against the password field of HTTP Basic auth. It ignores the username, so send anything or nothing.

That makes @token work directly with:

  • curl -u flag
  • Browser native auth dialogs
  • HTTP clients that only support Basic auth
  • Legacy systems and webhook integrations
Terminal window
# Username "admin", password is the token; the username is ignored
curl -u admin:my-secret-key-123 \
"https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/api/data"

A custom header, useful when a proxy or gateway has already claimed Authorization.

Terminal window
curl -H "X-Token: my-secret-key-123" \
"https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/api/data"

Pass the token in the URL. This suits quick testing, webhook callbacks, and browser links.

Terminal window
curl "https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/api/data?token=my-secret-key-123"

When authentication fails, the server returns:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="hoody-exec"
Content-Type: application/json
{
"error": "Unauthorized",
"message": "This endpoint requires authentication. Provide a valid token via Authorization: Bearer <token> header, X-Token header, ?token= query parameter, or HTTP Basic Auth."
}
  • WWW-Authenticate: Bearer triggers the native auth dialog in browsers.
  • The response body is the same whether the token is missing or wrong, so the reply leaks nothing about which one it was.
  • If the script configures CORS (@cors), the 401 response carries the CORS headers too.

When a script carries both @token and @cors, the server answers CORS preflight requests (OPTIONS) before the token check:

// @token my-secret-key-123
// @cors reflective
return { data: 'protected + CORS-enabled' };

Browsers send an OPTIONS preflight before any cross-origin request, and the HTTP spec does not let a preflight carry credentials. Requiring a token on the preflight would break CORS for every browser client.

The exchange runs in two steps:

  1. The browser sends OPTIONS with Origin and Access-Control-Request-Method, and the server returns 204 with the CORS headers. No token required.
  2. The browser sends the real GET or POST with Authorization: Bearer <token>, and the server checks the token before running the script.

This follows the CORS spec and is not a way around the gate: the request that reaches your code is still checked.


The @token gate also protects WebSocket connections. The check runs on the HTTP upgrade request, before the WebSocket handshake completes.

// @token my-secret-key-123
// @mode worker
// @websocket
ws.on('message', (socket, data) => socket.send('echo:' + data));

Send the token when you connect:

// Works in all WebSocket clients (including browsers)
// The WebSocket URL is the script's own route (file-based routing), not a dedicated /ws path
const ws = new WebSocket('wss://your-endpoint.containers.hoody.com/realtime/echo?token=my-secret-key-123');

Without a valid token, the server writes HTTP/1.1 401 Unauthorized to the socket and closes the connection. The WebSocket onerror / onclose event fires on the client.


Token comparison uses SHA-256 hashing on both sides followed by crypto.timingSafeEqual:

SHA-256(provided) === SHA-256(expected) // constant-time

This prevents timing attacks: the comparison takes the same amount of time regardless of how many characters match.

The token value is not returned in any API response or written to any log:

SurfaceRedaction
Access logs?token= replaced with ?token=[REDACTED]
Referer headers in logs?token= redacted
Scripts API (/api/v1/exec/scripts/read)Raw content shows // @token [REDACTED]
Magic Comments APItoken field returns [REDACTED]
metadata.parameters in your script?token= query param is removed before your code runs
Encoded bypass attempts (%74oken=)Caught by URL-parser fallback and redacted

When a client authenticates with ?token=, the server strips the token from the request URL before your script runs. Your script never sees it:

// @token my-secret
// Client calls: /api/data?token=my-secret&page=2
// Your script sees:
metadata.parameters // → { page: "2" } (no "token" key)
metadata.path // → /api/data (clean)

// @token sk_prod_a8f2e9c1d4b6
// @cors reflective
const userId = metadata.parameters.id;
const user = await db.getUser(userId);
return user;
// @token whsec_github_abc123
if (req.method !== 'POST') {
res.statusCode = 405;
return { error: 'Method Not Allowed' };
}
const payload = JSON.parse(req.rawBody.toString());
await processWebhook(payload);
return { received: true };
Terminal window
# GitHub webhook configured with:
# URL: https://your-endpoint.containers.hoody.com/webhooks/github?token=whsec_github_abc123
// @token realtime-secret-456
// @mode worker
// @websocket
// @cors reflective
if (!shared.connections) shared.connections = new Set();
ws.on('open', (socket) => shared.connections.add(socket));
ws.on('close', (socket) => shared.connections.delete(socket));
ws.on('message', (socket, data) => {
// Broadcast to all connected clients
for (const client of shared.connections) {
if (client !== socket) client.send(data);
}
});
Terminal window
# Read magic comments (token is redacted in response)
hoody exec magic-comments read -c CONTAINER_ID --path "api/data.ts" -o json
# → { "path": "api/data.ts", "comments": { "token": "[REDACTED]", "cors": "reflective" } }