Repository navigation
[Server] Accept plain http on *.localhost and 127.0.0.0/8 hosts in OAuth URLs - #620
Open
BrocksiNet wants to merge 1 commit into
Open
BrocksiNet wants to merge 1 commit into
BrocksiNet wants to merge 1 commit into
Conversation
…n OAuth URLs `SecureUrl` accepted plain http only for the exact hosts `localhost`, `127.0.0.1` and `::1`. Names under the reserved `.localhost` TLD resolve to loopback as well (RFC 6761, section 6.3), so `ProtectedResourceMetadata`, `OidcDiscovery` and `JwtTokenValidator::fromIssuer()` threw for local development setups served on hosts like `http://shop.localhost:8080`. Treat `localhost`, any `*.localhost` (case-insensitive, trailing dot allowed), the IPv4 loopback range `127.0.0.0/8` and `::1` as loopback, matching the hosts the W3C Secure Contexts specification treats as potentially trustworthy. Every other host still requires https.
BrocksiNet
requested review from
CodeWithKyrian,
Nyholm,
chr-hertel and
soyuka
as code owners
October 26, 2026 13:24
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues are reported for the expanded loopback-host OAuth URL validation.
No open issues 🎉
What changed in this PR
Expands OAuth URL validation to support local development hosts such as shop.localhost, addressing #619 while keeping HTTPS required for non-loopback hosts.
Changes:
- Accepts HTTP for
*.localhostand valid IPv4 addresses in127.0.0.0/8, with case-insensitive localhost matching and one optional trailing dot. - Adds tests for accepted loopback hosts and rejected lookalikes.
- Documents the expanded loopback support; DNS rebinding defaults remain unchanged.
| File | Description |
|---|---|
tests/Unit/Server/Transport/Http/OAuth/SecureUrlTest.php |
Adds loopback acceptance and lookalike rejection cases. |
src/Server/Transport/Http/OAuth/SecureUrl.php |
Extracts and expands loopback host detection. |
src/Server/Transport/Http/OAuth/JwtTokenValidator.php |
Updates the docblock to list accepted loopback hosts. |
docs/run/authorization.md |
Documents expanded HTTP support for development hosts. |
CHANGELOG.md |
Records the fix under version 0.9.1. |
Review effort: Balanced
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SecureUrltreatslocalhost, any*.localhost(case-insensitive, one trailing dot allowed), the IPv4 loopback range127.0.0.0/8and::1as loopback, so plain http is accepted for them. Every other host still requires https, and lookalikes such aslocalhost.example.com,notlocalhost,localhostx,.localhostor127.0.0.1.example.comstay rejected.*.localhostis reserved for loopback by RFC 6761, section 6.3. The W3C Secure Contexts specification treatslocalhost,*.localhost,127.0.0.0/8and::1as potentially trustworthy, which is the set this change matches. The IPv4 check only applies to valid dotted-quad literals, so a hostname starting with127.never matches.http://127.0.0.2rejection test: that address is loopback like127.0.0.1, and I found no reason in [Server] Narrow authorization to the resource server role #532 for excluding it. Happy to drop the127.0.0.0/8part if you prefer to keep IPv4 at127.0.0.1only.localhostor use HTTPS" (Communication Security). The SDK already relaxes https for loopback during development; this only makes that relaxation cover all loopback hosts.JwtTokenValidator::fromIssuer()docblock anddocs/run/authorization.mdlist the accepted hosts.DnsRebindingProtectionMiddlewarekeeps its exact defaultallowedHosts(localhost,127.0.0.1,[::1]): it is a configurable allow-list ofHostheaders with a different purpose, and widening a DNS rebinding default deserves its own discussion.Motivation: Shopware dev environments serve each checkout on
http://<name>.localhost:<port>. With SDK 0.9,ProtectedResourceMetadatathrows there, so OAuth discovery breaks in local development: shopware/shopware#21862Fixes #619
Test plan
SecureUrlTestcases: acceptedhttp://localhost,http://shop.localhost:8080,http://a.b.localhost,http://LOCALHOST.,http://Shop.LocalHost.:8080/mcp,http://127.1.2.3(plus the existing127.0.0.1,[::1]cases); rejectedhttp://localhost.example.com,http://shop.localhost.example.com,http://notlocalhost,http://localhostx,http://.localhost,http://10.0.0.1,http://127.0.0.1.example.com,http://[::ffff:127.0.0.1]make tests(2963 tests, 8 skipped)make phpstanmake cscomposer validate --strict