Upstreams that need a minted bearer: oauth2-client-credentials auth block + CIPP preset - #21
Merged
Merged
Conversation
Some third-party MCP servers (CIPP behind App Service Easy Auth) expect an
Authorization: Bearer <access token> rather than a static key — so a pasted
token dies within the hour. New optional spec block
auth: { kind: "oauth2-client-credentials", tokenUrl, clientId,
clientSecret: "kv:…", scope, header?, prefix? }
makes the gateway do the client-credentials exchange itself at connect time:
the secret is resolved from the store/env like any injected value, the token
is cached with the connection, and connect() rebuilds the transport once the
token is within 60s of expiry (headers are fixed per transport). Neither the
secret nor the token is logged. Also a CIPP preset — admin-only grants by
design: its tools arrive annotated read-only even when they surface LAPS
passwords and BitLocker keys.
Release v0.10.0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Why
CIPP's MCP endpoint (
/api/ExecMcp, behind App Service Easy Auth) wants a finishedAuthorization: Bearer <access token>, not a static key — verified against the NDR instance: 401 + PRM advertising the tenant's Entra as AS, and Easy Auth's allowed audiences include the CIPP API clients, so app-only tokens are accepted. Pasting such a token into an upstream spec works for exactly one hour.Planner-style upstreams don't have this problem because our servers accept long-lived credentials in headers and mint internally. For third-party servers the caller must mint — so the gateway learns to.
What
Optional upstream spec block:
${VAR}/bao:/kv:machinery (so only a reference is stored), the header defaults toAuthorization: Bearer …and is overridable.connect()tears down and rebuilds the connection once the token is within 60s of expiry — the next call transparently rides a fresh token.Plus a CIPP preset (url / tenant / client id / secret ref) with deliberately restrictive grants —
viewer: none, editor: none, admins only. Reason: CIPP exports its tools annotated read-only even forExecGetLocalAdminPassword,ExecGetRecoveryKey,ExecBreachSearch— so tier-derived access would hand LAPS passwords and BitLocker keys to every viewer.Tests
218 passing (8 new). New
upstream/oauth2-auth.test.tsruns a fake server that plays both the token endpoint and a bearer-protected MCP upstream, asserting: the grant shape (client_credentials, scope, secret pulled from the store), calls succeed with the minted token, a near-expiry token is re-minted and the call still succeeds (the fake rejects superseded tokens), and a broken token endpoint fails the connect.Release v0.10.0. After deploy: install CIPP via the preset (secret written on the Secrets tab first) so prod stops relying on the hand-pasted token.
🤖 Generated with Claude Code