Skip to content

[DISCUSSION] AuthFetch is super temperamental when used with Certificates. #22

Description

@sirdeggen

Migrated from bsv-blockchain/ts-sdk#464

I'm just noting that Claude Opus attempted to fix this for like an hour. Eventually it arrived as what might be a bug. Posting here just as a note to self to follow up and perhaps PR this.

Summary of Fixes
The root cause was a timing/synchronization issue between the client sending requests and the server processing certificates. Here's what was fixed:

  1. AuthFetch (ts-sdk) - Fixed infinite polling loop
    Replaced setInterval with recursive setTimeout
    Added 30-second timeout
    No more memory leaks

  2. Peer (ts-sdk) - THE KEY FIX
    Changed from throwing an error when certificates aren't validated yet, to waiting for certificate validation with a 30-second timeout
    The server-side Peer now polls the session manager until certificatesValidated === true before processing the general message

  3. auth-express-middleware - Multiple improvements
    Added ResponseWriterWrapper for cleaner response handling
    Fixed key mismatch in non-general handles
    Added error boundaries with try-catch-finally
    Added 30-second timeout for certificate waiting
    Improved debug logging

  4. age-verification backend - Application fix
    Added age.setVerifiedOver18(senderPublicKey) call when certificates are decrypted and over18 === 'true'
    The core architectural insight from comparing with the Go implementation: the Go version handles this synchronously, while the TypeScript version's async nature required explicit waiting/coordination between the certificate validation and general message processing.

The key fix was in Peer.ts - instead of immediately throwing an error when a general message arrives before certificates are validated:

// BEFORE: Threw error immediately
if (certificatesRequired && !certificatesValidated) {
  throw new Error(`Received general message before certificate validation...`)
}

// AFTER: Waits for certificates with timeout
while (Date.now() - startTime < CERTIFICATE_WAIT_TIMEOUT_MS) {
  const updatedSession = this.sessionManager.getSession(message.yourNonce)
  if (updatedSession?.certificatesValidated === true) {
    break
  }
  await new Promise(resolve => setTimeout(resolve, 100))
}

This allows the server to handle the race condition where the general message arrives slightly before certificate processing completes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions