# Callback server

The loopback HTTP listener that receives the OAuth authorization code redirect, per [RFC 8252 §7.3](https://datatracker.ietf.org/doc/html/rfc8252#section-7.3). Lives in `src/oauth/callbackServer.ts`; the public surface is defined by the module's exported types.

## Loopback bind

RFC 8252 §7.3 says clients SHOULD NOT assume a particular IP version is available and RECOMMENDS trying both. Implementation: bind `127.0.0.1` on an ephemeral port; on `EAFNOSUPPORT` / `EADDRNOTAVAIL` (no IPv4 loopback configured on this host) fall back to `[::1]` on a fresh ephemeral port. The returned `redirectURI` uses whichever literal actually got bound, so the browser connects to exactly what the authorization server redirects it to — no reliance on `localhost` DNS resolution.

Request handling additionally rejects non-loopback `remoteAddress` values with `403` as defense in depth against DNS-rebinding-style pivots — the listener only binds to a loopback interface, but enforcing it at the handler costs nothing.

## RFC 8252 conformance

| Clause | Requirement | Handled by |
| --- | --- | --- |
| §7.3 | IP literal, not `localhost` | Binds `127.0.0.1` or `[::1]`; redirect URI uses the literal. |
| §7.3 | Ephemeral OS-assigned port | `listen(0, ...)`; port read from `listening` event. |
| §7.3 | Attempt both IPv4 and IPv6 | IPv4-first, IPv6 fallback when the IPv4 family is unavailable. |
| §8.3 | Open the port only during the auth request | One-shot: closed on first consuming request, timeout, or abort. |
| §8.3 | Listen on loopback only | IP literal only; `remoteAddress` check as defense in depth. |
| §8.1 | PKCE | Out of scope — owned by the auth-URL + token-exchange layer. |
| §8.1 | Auth code interception mitigation | Success HTML does not echo `code`; CSP locks the page down (see [`callback-page.md`](./callback-page.md)). |
