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:
@@ -52,13 +52,22 @@ router.post("/identity/challenge", (_req: Request, res: Response) => {
|
||||
// event.kind — any (27235 recommended per NIP-98, but not enforced)
|
||||
|
||||
router.post("/identity/verify", async (req: Request, res: Response) => {
|
||||
const { event } = req.body as { event?: unknown };
|
||||
// Accept both { event } and { pubkey, event } shapes (pubkey is optional but asserted if present)
|
||||
const { event, pubkey: explicitPubkey } = req.body as { event?: unknown; pubkey?: unknown };
|
||||
|
||||
if (!event || typeof event !== "object") {
|
||||
res.status(400).json({ error: "Body must include 'event' (Nostr signed event)" });
|
||||
return;
|
||||
}
|
||||
|
||||
// If caller provided a top-level pubkey, validate it matches event.pubkey
|
||||
if (explicitPubkey !== undefined) {
|
||||
if (typeof explicitPubkey !== "string" || !/^[0-9a-f]{64}$/.test(explicitPubkey)) {
|
||||
res.status(400).json({ error: "top-level 'pubkey' must be a 64-char hex string" });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Validate event structure ──────────────────────────────────────────────
|
||||
const ev = event as Record<string, unknown>;
|
||||
const pubkey = ev["pubkey"];
|
||||
@@ -69,6 +78,12 @@ router.post("/identity/verify", async (req: Request, res: Response) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Assert top-level pubkey matches event.pubkey if both are provided
|
||||
if (typeof explicitPubkey === "string" && explicitPubkey !== pubkey) {
|
||||
res.status(400).json({ error: "top-level 'pubkey' does not match event.pubkey" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof content !== "string" || content.trim().length === 0) {
|
||||
res.status(400).json({ error: "event.content must be the nonce string" });
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user