Sign and verify session tokens (HS256) with WebCrypto
Maintainer antworten meist innerhalb von 1 Tag
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 1-2 Tage
- Anfängerfreundlichkeit
- 55/100
- Issue-Typ
- Feature
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- node.js, typescript
- Bereich
- authentication, backend, security
Rechercherichtung
Read packages/server/src/webhook.ts for the existing crypto.subtle HMAC usage, then create packages/server/src/security/session-token.ts and its tests at packages/server/tests/security/session-token.test.ts. Implement the specified compact HS256 token format, claim validation, origin and conversation checks, expiry skew, and key rotation; use RFC 7515 Appendix A.1 as a verification vector. Done means the listed acceptance tests pass, including malformed and tampered tokens.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Right now the widget picks its own conversationId and the server trusts it. With a shared store (Redis, Postgres), anyone who guesses another visitor's id can read that conversation's context and add to it. The fix in the next release is a short-lived signed session token: the server gives the widget a token bound to one conversation and one origin, and checks it on every request. This issue is the token format itself, as a new file with no dependencies. The /session route that hands tokens out comes later.
This one needs care, so it's for someone who has had a couple of PRs merged. I'll review it closely.
What to do
Create packages/server/src/security/session-token.ts. Use a compact JWS (header.payload.signature, base64url, no padding) with HS256 through crypto.subtle, so it runs on Node 22, Workers, Bun and Deno with no dependency.
export interface SessionClaims {
v: 1;
sid: string; // session id
cid: string; // conversation id
org: string; // origin the token was issued for
uid?: string;
tier?: string;
iat: number; // seconds
exp: number; // seconds
}
/** Imports a secret (at least 32 bytes as UTF-8) as an HMAC key. */
export function importSessionKey(secret: string): Promise<CryptoKey>;
/** Signs with keys[0] and puts its index in the header as `kid`. */
export function signSession(claims: SessionClaims, keys: CryptoKey[]): Promise<string>;
export function verifySession(
token: string,
keys: CryptoKey[],
opts: { origin: string | null; conversationId: string; now?: number; clockSkewSec?: number }
): Promise<
| { ok: true; claims: SessionClaims }
| { ok: false; code: 'malformed' | 'bad_signature' | 'expired' | 'origin_mismatch' | 'conversation_mismatch' }
>;
- Header:
{"alg":"HS256","typ":"JWT","kid":"<index>"}. Reject any otheralg, includingnone. - Verify with
crypto.subtle.verify, never by comparing strings. Try the key named bykidfirst, then the others, so rotating secrets doesn't log everyone out. clockSkewSecdefaults to 60 and applies toexp.- Check the signature before trusting anything in the payload. Return
malformedfor a token that doesn't have three parts, isn't valid base64url or JSON, or has a missing or wrongly typed claim. importSessionKeythrows a clear error when the secret is shorter than 32 bytes.- Don't create keys or call
crypto.subtleat module load. Workers don't allow that at global scope.
Where to look
packages/server/src/webhook.tsalready usescrypto.subtleHMAC for webhook signatures- RFC 7515, Appendix A.1, has an HS256 example with its key, usable as a test vector for verification
Acceptance criteria
- New
packages/server/src/security/session-token.tsandpackages/server/tests/security/session-token.test.ts - Round trip: sign, then verify, gives back the same claims
- Tests for an expired token, expired but within the skew, a changed payload, a changed signature,
alg: none, a wrong origin, a wrong conversation, a malformed token, and rotation (signed with an old key that's second in the list) - The RFC 7515 A.1 token verifies with its key (the claims check can be skipped for it)
- A secret shorter than 32 bytes throws
- Not exported from
@chatcops/serveryet, and no changeset needed (pnpm changeset --empty) -
pnpm test:coverageandpnpm lintpass
Want to work on this? Comment below and I'll assign it to you. Please take one issue at a time, branch off dev, and open your PR against dev with Closes #<this issue number>. Setup notes (pnpm, build before test) are in CONTRIBUTING.md.
- Vorherrschende Sprache
- TypeScript
- Sterne
- 13
- Forks
- 7
- Ø Merge
- 3 Std. 41 Min.
- Gemergte PRs (30 T.)
- 155
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Hat eine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus codercops/chatcops
-
Document the pre-chat formEvtl. vergeben @masyarakatai hat das vor 5 Tagen übernommen. Offendocumentation good first issue hacktoberfest widget
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 88/100
codercops/chatcops#70 · 5 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
docs: update the providers page for openai-compatible, registerProvider and provider importsEvtl. vergeben @prakashNalla hat das heute übernommen. Offendocumentation good first issue hacktoberfest website
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 76/100
codercops/chatcops#291 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
docs: add a protocol reference page for custom clientsEvtl. vergeben @kachamsiddarth hat das heute übernommen. Offendocumentation good first issue hacktoberfest website
codercops/chatcops#286 · 2 Kommentare · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
-
Create @chatcops/store-cloudflare (D1, KV and a Durable Object counter)Evtl. vergeben @bhushan4work hat das heute übernommen. Offenenhancement hacktoberfest help wanted server
Schwierigkeit 5/5 Über eine Woche Anfängerfreundlichkeit 25/100
codercops/chatcops#249 · 2 Kommentare · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
-
Create @chatcops/store-sqlite, a store for single-server setupsEvtl. vergeben @srikar-naidu hat das heute übernommen. Offenenhancement hacktoberfest help wanted server
Schwierigkeit 5/5 Über eine Woche Anfängerfreundlichkeit 35/100
codercops/chatcops#247 · 3 Kommentare · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in codercops/chatcops
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 83/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 1/5 1-3 Stunden Anfängerfreundlichkeit 72/100
zts212653/clowder-ai#1678 ·
Maintainer antworten meist innerhalb von 1 Tag
-
good first issue
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 64/100
Progressive-Victory/the-website#680 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
Maintainer antworten meist innerhalb von 1 Tag
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100