Resource Tokens
Short-lived, HMAC-signed tokens scoped to a single resource — the signed-URL primitive. An app backend asks Forge Core to issue a token for one resource, and anyone holding that token can ask Forge Core to decode it.
What this is (and isn't)
Forge doesn't know or care what a "resource" is — it just signs and verifies a small claim: this resourceId, this action, until this expiry. Serving the actual file or data once a token checks out is entirely up to your app (fetch from storage, proxy a file, redirect to a CDN URL, and so on).
Token format
A token looks like <base64url(payload)>.<base64url(HMAC-SHA256 signature)>. It's signed with a dedicated server secret (FORGE_RESOURCE_TOKEN_SECRET), kept separate from the Better Auth secret and the internal FORGE_CORE_SECRET so rotating one doesn't invalidate the others.
Issuing a token
Backend services authenticate the same way they do for /api/core/auth/verify — via x-forge-api-key.
curl -X POST http://localhost:3030/api/core/resource-tokens/issue \
-H "x-forge-api-key: fk_live_..." \
-H "Content-Type: application/json" \
-d '{"resourceId": "img_123", "action": "read", "ttlSeconds": 300}'{
"token": "eyJyZXNvdXJjZUlkIjoiaW1nXzEyMyIs...",
"resourceId": "img_123",
"action": "read",
"expiresAt": "2026-09-06T16:05:00.000Z"
}ttlSeconds defaults to 300 (5 minutes) and is capped at 3600 (1 hour). An optional metadata object is embedded in the token verbatim and returned unchanged on decode — useful for carrying small hints like an image variant ({"size": "thumb"}) without a second lookup.
Decoding a token
Decoding does not require an API key — the token itself is the credential, the same trust model as an S3 presigned URL. Whoever holds the token can ask Forge Core whether it's still valid and what it grants.
curl -X POST http://localhost:3030/api/core/resource-tokens/decode \
-H "Content-Type: application/json" \
-d '{"token": "eyJyZXNvdXJjZUlkIjoiaW1nXzEyMyIs..."}'{
"valid": true,
"resourceId": "img_123",
"action": "read",
"issuedAt": "2026-09-06T16:00:00.000Z",
"expiresAt": "2026-09-06T16:05:00.000Z",
"metadata": null
}Forge doesn't serve the resource itself
This is intentionally just the sign/verify primitive. Your app's own resource-serving layer calls decode, checks that resourceId/action match what's being requested, and only then fetches or streams the actual file.
Failure reasons
An expired, tampered, or malformed token returns 401 with {"valid": false, "reason": "..."}.
| Reason | Meaning |
|---|---|
malformed | Token isn't the expected two-part signed format |
invalid_signature | Signature doesn't match (tampered, or signed with a different secret) |
expired | Token's expiry has passed |
Related environment variable
FORGE_RESOURCE_TOKEN_SECRET— required at boot; the HMAC signing key for all resource tokens. Seedocumentation/API.mdfor the full request/response shapes.