Skip to content

Let a sign-in reach a containerised MCP server - #92

Merged
MathiasWP merged 1 commit into
mainfrom
fiber-auth-not-refreshing
Aug 27, 2026
Merged

Let a sign-in reach a containerised MCP server#92
MathiasWP merged 1 commit into
mainfrom
fiber-auth-not-refreshing

Conversation

@MathiasWP

Copy link
Copy Markdown
Owner

Under ToolHive the MCP server read its credentials from FIBER_SECRETS once at startup, so a container held whatever was true when it began — you signed in, the keychain got the new token, and the server went on presenting the expired one until someone re-exported the secrets and replaced the workload.

Credentials now travel through the collections directory the container already mounts: the app rewrites that file whenever a credential changes, the server re-reads it, and the next call picks the new value up. The file is sealed with XChaCha20-Poly1305 and the key stays out of the mount — keychain on the app's side, ToolHive's encrypted store on the container's — so a copy of it alone is inert; its existence is the opt-in, so a desktop-only install never has credentials on disk.

Bearer collections needed a second fix to benefit, since a static token cannot be refreshed by replaying a request and so a 401 never dropped it — a rejected credential is now dropped whenever it came from a source that can change underneath the process, which leaves the desktop app untouched. Adds fiber mcp file-key and fiber mcp export-secrets --to <path>, wired up by scripts/toolhive.sh.

Verified with 146 passing tests (7 new, including an end-to-end one that fails with a 401 when the fix is reverted), clippy and fmt clean on both the GUI and --no-default-features builds; a real ToolHive container was not run, since that needs Docker plus thv and writes a key to the developer's actual keychain.

Under ToolHive the server read its credentials from FIBER_SECRETS once at
startup, so a container held whatever was true when it began: you signed in,
the keychain got the new token, and the server went on presenting the expired
one until someone re-exported the secrets and replaced the workload.

Credentials can now travel through the collections directory the container
already mounts. The app rewrites that file whenever a credential changes and
the server re-reads it, so the next call picks the new value up. The file is
sealed with XChaCha20-Poly1305 and the key stays out of the mount — keychain
on the app's side, ToolHive's encrypted store on the container's — so a copy
of it alone is inert. Its existence is the opt-in: toolhive.sh creates it, the
app writes to it only if it is already there, and deleting it opts back out.

Bearer collections needed a second fix to benefit. A static token cannot be
refreshed by replaying a request, so a 401 never dropped it, and a zero-TTL
cache entry has nothing else to expire it — a container would have presented
its startup token for the life of the workload even with a live file. A
rejected credential is now dropped whenever it came from a source that can
change underneath the process. The desktop app is unaffected: it has no such
source, and the same line there would cost a keychain prompt per 401.
@MathiasWP
MathiasWP merged commit 2414209 into main Aug 27, 2026
4 checks passed
@MathiasWP
MathiasWP deleted the fiber-auth-not-refreshing branch August 27, 2026 12:42
@github-actions github-actions Bot mentioned this pull request Aug 27, 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