diff options
| author | Adam Soltys <[email protected]> | 2026-06-27 23:08:36 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-06-27 23:08:36 -0700 |
| commit | 45e6e21024e6a8491fa07f53b931263cdeac3d8b (patch) | |
| tree | b625ff73bdddf118aeb174f0733be00e4d97fe0c /lib | |
| parent | ea23e9a5ba360ab77a16dfb8e48e5b2471fee8c4 (diff) | |
| download | coinos-server-45e6e21024e6a8491fa07f53b931263cdeac3d8b.tar.gz coinos-server-45e6e21024e6a8491fa07f53b931263cdeac3d8b.zip | |
auth: hard-evict banned accounts at the JWT layer
Add an `evicted` set check in the JWT strategy: an evicted account fails
authentication on every request and every endpoint, regardless of source
IP. The existing blacklist only blocks sends, so a compromised/abusive
JWT could still authenticate and read/probe; eviction kills it outright.
Matches on uid or username so a rename can't evade it.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/auth.ts | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/lib/auth.ts b/lib/auth.ts index 79c04e9d..cae73a46 100644 --- a/lib/auth.ts +++ b/lib/auth.ts @@ -1,4 +1,5 @@ import config from "$config"; +import { db } from "$lib/db"; import { fail, getUser } from "$lib/utils"; import fastifyPassport from "@fastify/passport"; import jwt from "passport-jwt"; @@ -54,6 +55,19 @@ export const jwtStrategy = new jwt.Strategy( id = id.slice(0, -3); const user = await getUser(id); + + // Hard eviction: an account in the `evicted` set cannot authenticate AT ALL + // — every request, every endpoint — regardless of source IP/VPN. Unlike the + // `blacklist` freeze (which only blocks sends), this kills the value of a + // compromised/attacker JWT outright. Match on the immutable uid OR username + // so a rename can't shake it. + if ( + user && + ((await db.sIsMember("evicted", user.id)) || + (await db.sIsMember("evicted", user.username?.toLowerCase?.().trim()))) + ) + return next(null, false); + next(null, user); }, ); |
