fix(server): native-redirect review fixes before v0.44.0 - #526
Merged
Merged
Conversation
ApplicationType gains the helpers ClientAuthMethod and SenderConstrain
already have, mapping OIDC Registration's application_type wire values
("web", "native"), for deployments that read client registrations
from configuration.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…irect policy #524 parsed every authorization response permissively at build time, on the grounds that the pushed authorization request had already checked redirect_uri against the client's type. BuildAuthorizationErrorRedirect never goes through one: it checked only that the URI was registered. So under production assurance a web client registered for a loopback or private-use URI got an error redirect there, which FAPI 2.0 forbids and v0.43.0 refused. It now applies parseRedirectURI as PAR does. PAR's refusal of a native app's redirect URI on a client registered as web now names ApplicationTypeNative in its cause, for the logs: the first mistake a wallet's integrator makes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A private-use redirect URI with an empty authority (com.example.app:///cb, or :////host/cb) passed as scheme:/path. It's now refused, with a message that shows the single-slash form RFC 8252 §7.1 writes (com.example.app:/callback, not com.example.app://callback). - A native client's loopback redirect URI must be the literal 127.0.0.1 or ::1. net.IP.Equal also took the IPv4-mapped ::ffff:127.0.0.1. - A URI with no host is refused by ParseIssuerURL and ParseEndpointURL as having no host, rather than as not absolute. - Docs: AllowLoopbackHTTP, URLOption, AllowPrivateUseScheme, ApplicationTypeNative and HasRedirectURI now describe the native exceptions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
server/assurance.go, ARCHITECTURE, GETTING_STARTED and README said loopback http redirect URIs were development-only; that's a web client's rule, and a native client's are accepted in production. GETTING_STARTED shows the single-slash private-use form, and README lists RFC 8252. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
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
These are the fixes from the security and DevX review of #524 (native-app redirect URIs), before v0.44.0. There are four commits, for release-please.
fix(server):BuildAuthorizationErrorRedirectskipped the redirect policy (Low regression, both reviews found it).redirect_urito the client's type.BuildAuthorizationErrorRedirectnever goes through PAR; it only checked that the URI was registered.http://127.0.0.1/callback,http://localhost/callbackor a private-use URI got an error redirect there, carryingerrorandstate. FAPI 2.0 forbids that, and v0.43.0 refused it.parseRedirectURI(client, …), as PAR does.PAR's refusal of a native URI on a client registered as web now names
ApplicationTypeNativein its cause (for logs, never the response). That's the first mistake a wallet integrator makes.fix: stricter native URI forms and clearer messages.com.example.app:///cb,:////host/cb) are refused. The error shows the single-slash form RFC 8252 §7.1 writes:com.example.app:/callback, notcom.example.app://callback.127.0.0.1or::1;net.IP.Equalalso accepted the IPv4-mapped::ffff:127.0.0.1.ParseIssuerURLandParseEndpointURLnow say a hostless URI "must have a host" instead of the misleading "must be absolute".feat(storage):ApplicationType.String/IsValidandParseApplicationTypefor the"web"/"native"wire values, matchingClientAuthMethodandSenderConstrain.docs: several docs said loopback http redirects are development-only. That's the web client's rule, so I updated the native exceptions in:server/assurance.go;AllowLoopbackHTTP,URLOption,AllowPrivateUseScheme,ApplicationTypeNativeandHasRedirectURI;GETTING_STARTED now shows the single-slash form and corrects "a web client can use neither" (it can use loopback under development). README lists native apps and RFC 8252.
Deferred: per-authorization redirect URIs in the FAPIgo client, for a desktop wallet that binds a new port each flow. One
*client.Clientper listener works today.Tests
TestBuildAuthorizationErrorRedirectHoldsTheRedirectPolicy(production): web clients with loopback,localhostor private-use URIs are refused; native clients with private-use or loopback URIs are accepted.TestPARNamesTheNativeRegistration: the cause namesApplicationTypeNativefor a native URI on a web client, and doesn't for a URI no registration admits.TestParseRedirectURLandTestParseRedirectURLSaysWhatToChange::///and:////hostare refused;com.example.app:/path;TestNativeRedirectURIsAtRegistrationgains the[::ffff:127.0.0.1]refusal.TestApplicationTypeWireValuesround-trips"web"and"native"and refuses"","Native"and"mobile".go test -raceacross fapi, storage, server, federation and client passes.go test ./cmd/... ./fapitest/...passes.FuzzParseRedirectURL(15 seconds) is clean.🤖 Generated with Claude Code