fix(#26): tighten token handling and verify API contract
- resolveNostrPubkey() now returns { pubkey, rejected } instead of string|null
so invalid/expired tokens return 401 instead of silently falling to anonymous
- POST /sessions and POST /jobs: return 401 if nostr_token header/body is
present but invalid or expired
- POST /identity/verify: now accepts optional top-level 'pubkey' field alongside
'event'; asserts pubkey matches event.pubkey if both are provided — aligns
API contract with { pubkey, event } spec shape and hardens against mismatch
This commit is contained in:
@@ -138,13 +138,20 @@ async function advanceTopup(session: Session): Promise<Session> {
|
||||
|
||||
// ── Resolve Nostr pubkey from token header or body ────────────────────────────
|
||||
|
||||
function resolveNostrPubkey(req: Request): string | null {
|
||||
/** Resolves a Nostr token from the request.
|
||||
* Returns `{ pubkey, rejected }` where:
|
||||
* rejected=false, pubkey=null → no token supplied (anonymous)
|
||||
* rejected=true, pubkey=null → token supplied but invalid/expired → caller should 401
|
||||
* rejected=false, pubkey=str → valid token
|
||||
*/
|
||||
function resolveNostrPubkey(req: Request): { pubkey: string | null; rejected: boolean } {
|
||||
const header = req.headers["x-nostr-token"];
|
||||
const bodyToken = req.body?.nostr_token;
|
||||
const raw = typeof header === "string" ? header : (typeof bodyToken === "string" ? bodyToken : null);
|
||||
if (!raw) return null;
|
||||
if (!raw) return { pubkey: null, rejected: false };
|
||||
const parsed = trustService.verifyToken(raw.trim());
|
||||
return parsed?.pubkey ?? null;
|
||||
if (!parsed) return { pubkey: null, rejected: true };
|
||||
return { pubkey: parsed.pubkey, rejected: false };
|
||||
}
|
||||
|
||||
// ── POST /sessions ─────────────────────────────────────────────────────────────
|
||||
@@ -161,7 +168,12 @@ router.post("/sessions", sessionsLimiter, async (req: Request, res: Response) =>
|
||||
}
|
||||
|
||||
// Optionally bind a Nostr identity — ensure row exists before FK insert
|
||||
const nostrPubkey = resolveNostrPubkey(req);
|
||||
const tokenResult = resolveNostrPubkey(req);
|
||||
if (tokenResult.rejected) {
|
||||
res.status(401).json({ error: "Invalid or expired nostr_token" });
|
||||
return;
|
||||
}
|
||||
const nostrPubkey = tokenResult.pubkey;
|
||||
if (nostrPubkey) await trustService.getOrCreate(nostrPubkey);
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user