mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-05 16:37:46 +00:00
fix(api-tokens): harden rate limiting and surface list-load errors (#1292)
* fix(api-tokens): scope per-token rate limits to live tokens Forged or token-shaped Authorization headers no longer mint their own rate-limit budget. The key generator now grants a per-token budget only to a real, active token and falls back to per-IP keying for anything else, so a single source cannot evade the global limiter by rotating fake tokens. The validated token is memoized on the request, so authentication reuses it without a second database lookup. Token validation (format, checksum, lookup, revocation, expiry) is now a single shared helper used by the HTTP auth middleware, the WebSocket upgrade handler, and the rate-limit key generator, replacing two near-identical inline copies that could drift apart. The last-used timestamp write is throttled so a busy token no longer writes to the database on every request. * fix(api-tokens): surface token list-load failures with a retry A failed load of the API tokens list was swallowed: a server error rendered the empty "no tokens yet" state with no sign that anything went wrong. The list now shows an error card with a Retry action and raises a toast on any non-ok response or network error, matching the create and revoke flows. Adds a troubleshooting entry for the error. * test(api-tokens): seed tokens via the shared test helper The new hardening and WS-scope suites computed sha256 of a raw token directly, which CodeQL flags as js/insufficient-password-hash (a false positive: these are 256-bit CSPRNG opaque tokens, not passwords). Route token creation through the existing apiTokenTestHelper and read the stored token_hash back from the row, so the suites no longer hash anything themselves. Also removes the duplicated createToken helpers. * fix(api-tokens): key the rate limiter by the same credential auth uses The rate-limit key generator checked the session cookie before the Authorization bearer, while authMiddleware authenticates bearer-over-cookie (bearerToken || cookieToken). A request could send a Bearer API token plus a forged cookie and be keyed by the cookie's (forgeable, rotatable) username, sidestepping the per-token / per-IP keying the limiter applies to API tokens: a valid token would lose its own bucket, and a forged token-shaped bearer would no longer collapse to per-IP. Reorder the generator to mirror auth: process the bearer first (validate the API token and key per-token or fall back to per-IP; otherwise decode the JWT by username/sub), and consult the cookie only when there is no bearer. Regression tests cover a valid and a forged sen_sk_ bearer, each sent with a forged cookie.
This commit is contained in:
@@ -360,6 +360,10 @@ Read Only is sufficient for the notification stream.
|
||||
<Accordion title="The API Tokens tab is missing from Settings">
|
||||
The tab is admin-only. Sign in as an admin user to see it. Tokens are also issued from the hub; if you have selected a remote node in the node switcher, switch back to the local hub and the tab will appear under **Settings → Identity**.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="The token list shows `Couldn't load API tokens`">
|
||||
The list could not be fetched. Use the **Retry** button on the error card to reload. If it persists, confirm you are signed in as an admin and that the hub is reachable, then check the browser console and the hub logs for the underlying error. An empty list with no error card simply means you have not created any tokens yet.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## FAQ
|
||||
|
||||
Reference in New Issue
Block a user