Skip to content

fix(selfhost): warn when a deploy clears Managed OAuth on the Access app - #307

Open
eduyubero wants to merge 1 commit into
every-app:mainfrom
eduyubero:fix/selfhost-access-oauth-configuration
Open

fix(selfhost): warn when a deploy clears Managed OAuth on the Access app#307
eduyubero wants to merge 1 commit into
every-app:mainfrom
eduyubero:fix/selfhost-access-oauth-configuration

Conversation

@eduyubero

Copy link
Copy Markdown

Refs #304.

Problem

Self-host MCP authentication depends on Managed OAuth being enabled on the Cloudflare Access application — docs/SELF_HOSTING_CLOUDFLARE_OPERATIONS.md has the operator turn it on by hand. Running pnpm deploy:selfhost again silently undoes it.

Cloudflare.Access.Application exposes no oauthConfiguration prop, and alchemy's reconcile sends a PUT-style body assembled only from declared props (buildMutableBody), so Cloudflare drops oauth_configuration.

What makes it expensive is the distance between cause and symptom: a routine version update breaks MCP, and the failure appears days later inside an MCP client as Unexpected content type: text/html — Access serving its login page. Nothing connects the two.

Change

  • Read the live setting before the application reconciles, and print a reminder on the deploy output when the deploy cleared it.
  • Document the behaviour next to the enable steps, with a way to check the current state.

Why this reports rather than repairs

I tried re-applying the setting after reconcile and backed it out. It needs a full-replace PUT on the Access application, which carries the allow-policy: a mistake there doesn't degrade, it removes the gate. Alchemy also returns applicationId as a lazy Output<string> and the client's errors don't fit the stack's typed error channel, so the code fought the framework throughout.

The declarative fix looks like it belongs upstream in alchemy — Access.Application gaining an oauthConfiguration passthrough, at which point this repo's side is a two-line declaration and alchemy's own provider handles the full-body PUT it already does correctly. @distilled.cloud/cloudflare already accepts the field (zero-trust.ts:2538, serialised at :2996). Happy to take that on if you agree with the direction, or to swap this for a real fix if you would rather it live here.

The read is best-effort: any failure collapses to "no warning", which is exactly today's behaviour. It cannot fail a deploy.

Verification

  • pnpm ci:check passes.
  • The mechanism is confirmed on a live self-host deployment: Managed OAuth enabled by hand, oauth_configuration observed as null after a subsequent deploy, MCP failing with the text/html error above.
  • Not verified: the new warning has not been exercised against a live deploy — I did not want to clear Managed OAuth again on the instance I was testing from. The read path is a list-and-match on domain; worth a look on that basis.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EZja8vK2mx6gf2BfZMAXDj

Self-host MCP authentication depends on Managed OAuth being enabled on the
Cloudflare Access application, which the operations guide has the operator
turn on by hand. Deploying again silently undoes it: alchemy's
Access.Application exposes no oauthConfiguration prop, and its reconcile
sends a PUT-style body assembled only from declared props, so Cloudflare
drops oauth_configuration.

The failure then surfaces much later and somewhere else entirely — an MCP
client reporting `Unexpected content type: text/html`, which is Access
serving its login page — with nothing tying it back to a routine version
update days earlier.

Read the live setting before the resource reconciles and, when the deploy
cleared it, say so on the deploy output. Also document the behaviour and
how to check the current state next to the enable steps.

This reports the problem rather than fixing it: re-applying the setting
means a full-replace PUT on the application, which would carry the
allow-policy with it, and the declarative fix belongs upstream in alchemy
(the underlying @distilled.cloud client already accepts
oauthConfiguration). The read is best-effort and can never fail a deploy.

Refs every-app#304

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZja8vK2mx6gf2BfZMAXDj
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant