Repository navigation
datasource-oauth: admit http for local_egress-listed loopback addresses, so the authorization-code + PKCE grant can be proven against a local stub #1101
Description
The authorization-code + PKCE grant of a callable source cannot be proven against a local stub provider. The datasource-oauth/providers registration refuses every non-https authorize and token URL, including addresses that datasource-oauth/local_egress lists. The "Local egress" section says the allowance covers that exchange.
Found while proving obin-ai/platform-core#42 at v0.0.95. The full proof (script, stub, command, output) is in https://github.com/obin-ai/platform-core/issues/42#issuecomment-6134054905.
Evidence (v0.0.95, 4580390a)
- The refusal.
ConfigureDatasourceOAuth(module/services/accounts/code/pkg/business/datasource_oauth.go:33) returns
datasource OAuth endpoints must be absolute HTTPS URLs
atdatasource_oauth.go:54for anyauthorize_url/token_urlwhose scheme is nothttps.- accounts calls it during setup at
module/services/accounts/code/work.go:370and returns the error. - So a registration naming a loopback http stub stops accounts. I read this from the code; I did not boot it with such a registration.
- accounts calls it during setup at
- The documentation says otherwise.
module/CALLABLE_SOURCES.md:221("Local egress"): "It applies to the token exchange (refresh,client_credentials, authorization-code) and the operation call alike." - The registration is the only thing in the way.
- The token exchange itself accepts
http(pkg/datasource/apisource/client.go:377). local_egressadmits the listed loopbackip:portat dial time (pkg/datasource/apisource/local_egress.go:61).- With
local_egress=127.0.0.1:18080,127.0.0.1:18081, theclient_credentialsgrant against an http stub on those addresses passed end to end on v0.0.95: connect, declare,datasource.Invoke,Lookup, the stub received the host-minted bearer, and the credential was sealedcfs1:vault-transit:. - Command, from a platform-core checkout with that value in an uncommitted
configurations/local/datasource-oauth.env, CLI 0.1.185:codefly run service frontend --fixture dev-admin --headless --naming-scope pc42 HOST_LOG=<that log> ./run.sh
- The token exchange itself accepts
- The consent redirect can already be driven locally over the API. Nothing beyond the registration blocks it:
BeginDatasourceAccountLink(pkg/business/datasource_directory.go:259) returnsoauthAccountLinker.AuthorizeURL(datasource_oauth.go:91), with an S256code_challenge.- A stub
/authorizecan auto-consent and redirect toredirect_uriwithcodeandstate. CompleteDatasourceAccountLinktakes them.- The host exchanges the code with its
code_verifier(datasource_oauth.go:139).
- No TLS workaround. Serving the stub over https would need a certificate the host trusts, meaning a mounted CA. That breaks the security posture (no mounted files), so the authorization-code grant stays not verified on Generate service secret configuration declarations from topology #42.
Ask
Admit http for a datasource-oauth/providers registration only when both of these hold:
-
Under the same local-runtime refusal rules as feat(accounts): a local runtime may list loopback stubs a callable source can reach #1089:
- the Codefly environment is
local, and - the process is not in a Kubernetes pod.
That is the predicate
configureLocalEgressuses (work.go:2657,work.go:2703:isLocal && !infra.InCluster()). - the Codefly environment is
-
Both
authorize_urlandtoken_urlname an exactip:portentry oflocal_egress: a loopback IP literal, no hostname (notlocalhost), and the same port.
Everything else refuses exactly as today: non-local runtimes, unlisted addresses, hostnames, and http anywhere outside that case.
Startup order matters here. configureLocalEgress runs first in requireStartupConfiguration; ConfigureDatasourceOAuth must read the allowance it installed, not re-parse the value differently.
Done when
- The full consent redirect is proven locally against a loopback http stub. A test (and/or the documented local proof) covers the whole chain:
BeginDatasourceAccountLink;- stub
/authorizeauto-consents; - redirect with
code/state; CompleteDatasourceAccountLink;- the token exchange, with the stub checking
code_verifieragainst the S256code_challengeit received; - a sealed envelope;
- a successful
InvokeSourceOperationon the resulting personal source.
- A non-local runtime still refuses an http registration (environment not
local, or in-cluster), naming the key. - An http registration whose address is not listed in
local_egressis refused, as is a hostname spelling. CALLABLE_SOURCES.md"Local egress" andmodule/configurations/README.mddescribe the rule.
Related: #1049 (callable sources), #1087 / #1089 (local egress).
Not started. Filed from obin-ai/platform-core#42 with the owner's approval.
Activity