Skip to content

fix(encrypted-secrets): store tokens at org partition for Service Token compatibility#1398

Closed
myohei wants to merge 1 commit into
UsefulSoftwareCo:mainfrom
myohei:fix/encrypted-secrets-org-partition
Closed

fix(encrypted-secrets): store tokens at org partition for Service Token compatibility#1398
myohei wants to merge 1 commit into
UsefulSoftwareCo:mainfrom
myohei:fix/encrypted-secrets-org-partition

Conversation

@myohei

@myohei myohei commented Jul 10, 2026

Copy link
Copy Markdown

Problem

When using Service Token authentication (e.g. MCP clients via Cloudflare Access), OAuth tokens saved during browser OAuth (by a human subject) are invisible to the Service Token subject.

This causes oauth_connection_missing / oauth_reauth_required errors when an MCP client (authenticated with a Service Token) tries to call a tool on an integration whose OAuth was completed in the browser.

Root Cause

The encrypted-secrets provider's ownerOf() returns "user" when the executor has a non-null subject. During browser OAuth, the token is stored at:

plugin_storage: owner='user', subject='<human_account_id>'

During Service Token API calls, the plugin_storage onRead policy filters by:

tenant = current AND (owner = 'org' OR (owner = 'user' AND subject = current))

The Service Token has a different subject (common_name), so the stored token row is invisible → null → connection appears to have no credential.

Fix

Always store encrypted secrets at owner='org' so any subject within the tenant (human user or Service Token) can retrieve them.

Access control remains enforced by the connection row's (tenant, owner, subject) partition — the provider is a shared, opaque-key vault.

Test

Added a cross-subject visibility test that mirrors the real onRead policy, verifying that a token stored by one subject is retrievable by another within the same tenant.

…ct visibility

When using Service Token auth (e.g. MCP clients via Cloudflare Access),
tokens saved during browser OAuth (by a human subject) were invisible
to the Service Token subject due to the owner-read policy on
plugin_storage.

Always store encrypted secrets at owner='org' so any subject within
the tenant can retrieve them. Access control remains enforced by the
connection row's (tenant, owner, subject) partition.
@myohei myohei closed this Jul 10, 2026
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