Make loopback redirect port variance opt-in for public clients#58
Conversation
RFC 8252 scopes the any-port loopback carve-out to native apps, which are public clients (Section 8.4). Confidential clients have a stable redirect endpoint and no legitimate need for ephemeral-port loopback redirects, so RedirectUris::matches() now takes an allowLoopback flag that is off by default: exact matching always applies, and the port variance only unlocks when the caller opts in for a public client.
Greptile SummaryThis PR makes the RFC 8252 §7.3 loopback port-variance opt-in via a new
Confidence Score: 5/5Safe to merge — the change narrows the default matching surface and introduces no new code paths that could permit unintended redirects. The implementation is a clean, minimal guard added before the loopback branch; exact matching is unaffected, and the new flag is default-off so the overall redirect-target surface shrinks rather than expands. The test suite covers all three loopback hosts, both port combinations, case-normalization, path-normalization, and scheme/component strictness with both flag values. No files require special attention. Important Files Changed
Reviews (2): Last reviewed commit: "(test): allow hyphenated adjectives in p..." | Re-trigger Greptile |
Phrase's adjective list includes 'Quick-witted' and 'Fun-loving', so testGenerate failed whenever the random draw picked one of them.
What
RedirectUris::matches()now takes anallowLoopbackflag (defaultfalse). Exact matching always applies — including for loopback URIs — but the RFC 8252 §7.3 any-port loopback fallback only unlocks when the caller opts in.Why
RFC 8252 scopes the loopback port carve-out to native apps, which are public clients (§8.4) — they bind an ephemeral port per run and cannot register it ahead of time. A confidential client is a server that can hold a secret: it has a stable, routable redirect endpoint and no legitimate need for ephemeral-port loopback redirects, so extending the looseness to it just widens the redirect-target surface. Other implementations gate the same way (e.g. Ory Hydra applies port-insensitive loopback matching only to
token_endpoint_auth_method: noneclients).Callers pass their public-client discriminator, e.g.:
Behavior change
The default flips from loose to strict for the loopback port variance introduced in 0.9.0 — releasing as 0.9.1 since 0.9.0 has no merged consumers of the loose behavior. (The Appwrite Cloud adoption PR is unmerged and will pass the flag.)
Testing
bin/monorepo test auth— 200 tests, 447 assertions, green;bin/monorepo check authclean