From db8f0f4ced7e88a889d3beb9ef91c3d64817313d Mon Sep 17 00:00:00 2001 From: Bas van den Aakster Date: Sun, 16 Nov 2025 17:51:04 +0100 Subject: [PATCH] Fix answerer authorization for ICE candidates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The answerer was getting 403 Forbidden when sending ICE candidates because the server didn't know who the answerer was yet. ICE gathering starts when setLocalDescription is called, but we were calling /answer AFTER that. Fixed by sending the answer to the server BEFORE setLocalDescription: 1. Create answer SDP 2. Send answer to server (registers answererPeerId) 3. Set up ICE handler 4. Set local description (ICE gathering starts) This ensures the server has answererPeerId set before ICE candidates arrive, so they're properly authorized. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/peer/answering-state.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/peer/answering-state.ts b/src/peer/answering-state.ts index a14dd7f..75fcd8a 100644 --- a/src/peer/answering-state.ts +++ b/src/peer/answering-state.ts @@ -23,15 +23,19 @@ export class AnsweringState extends PeerState { sdp: offerSdp }); + // Create answer + const answer = await this.peer.pc.createAnswer(); + + // Send answer to server BEFORE setLocalDescription + // This registers us as the answerer so ICE candidates will be accepted + await this.peer.offersApi.answer(offerId, answer.sdp!); + // Enable trickle ICE - set up handler before ICE gathering starts this.setupIceCandidateHandler(); - // Create answer - const answer = await this.peer.pc.createAnswer(); - await this.peer.pc.setLocalDescription(answer); // ICE gathering starts here - - // Send answer to server immediately (don't wait for ICE) - await this.peer.offersApi.answer(offerId, answer.sdp!); + // Set local description - ICE gathering starts here + // Server already knows we're the answerer, so candidates will be accepted + await this.peer.pc.setLocalDescription(answer); // Transition to exchanging ICE const { ExchangingIceState } = await import('./exchanging-ice-state.js');