Hacktoberfest 2026: as issues que os mantenedores marcaram para outubro, abertas e boas para iniciantes. Ver issues do Hacktoberfest

Sign and verify session tokens (HS256) with WebCrypto

Aberta
#230 0 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
4/5
Tempo estimado
1-2 dias
Facilidade para iniciantes
55/100
Tipo de issue
Funcionalidade
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
node.js, typescript

Direção de pesquisa

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.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

enhancement hacktoberfest help wanted server

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 other alg, including none.
  • Verify with crypto.subtle.verify, never by comparing strings. Try the key named by kid first, then the others, so rotating secrets doesn't log everyone out.
  • clockSkewSec defaults to 60 and applies to exp.
  • Check the signature before trusting anything in the payload. Return malformed for a token that doesn't have three parts, isn't valid base64url or JSON, or has a missing or wrongly typed claim.
  • importSessionKey throws a clear error when the secret is shorter than 32 bytes.
  • Don't create keys or call crypto.subtle at module load. Workers don't allow that at global scope.

Where to look

  • packages/server/src/webhook.ts already uses crypto.subtle HMAC 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.ts and packages/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/server yet, and no changeset needed (pnpm changeset --empty)
  • pnpm test:coverage and pnpm lint pass

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.

Linguagem predominante
TypeScript
Estrelas
13
Forks
7
Merge médio
4h 11min
PRs com merge (30d)
122

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de codercops/chatcops

Todas as issues de codercops/chatcops

Issues semelhantes

Mais issues de TypeScript

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.