aboutsummaryrefslogtreecommitdiffstats
path: root/lib/auth.ts
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-06-27 23:08:36 -0700
committerAdam Soltys <[email protected]>2026-06-27 23:08:36 -0700
commit45e6e21024e6a8491fa07f53b931263cdeac3d8b (patch)
treeb625ff73bdddf118aeb174f0733be00e4d97fe0c /lib/auth.ts
parentea23e9a5ba360ab77a16dfb8e48e5b2471fee8c4 (diff)
downloadcoinos-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/auth.ts')
-rw-r--r--lib/auth.ts14
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);
},
);