MCP OAuth 2.1 and OAuth 2.0
Choose the protocol mode deliberately
Section titled “Choose the protocol mode deliberately”DeepIntShield offers two shared-connection OAuth modes in Agentic → MCP Registry → Add MCP Server:
- OAuth 2.1 (MCP 2026-07-28) is the strict mode for MCP resources that implement the current authorization profile. It requires protected-resource discovery, issuer binding, authorization code with PKCE S256, exact resource indicators, safe endpoint handling, encrypted persistence, and one-use callback state.
- OAuth 2.0 preserves compatibility with older providers and existing configurations. It does not claim the stricter MCP discovery and issuer guarantees.
Both modes authorize the MCP connection. Calls without
X-MCP-Subject-Token use that connection’s shared grant. They do not turn the
person who completed the consent screen into the GAF agent or a per-call user.
For per-caller upstream credentials, see
Delegated MCP authentication.
OAuth applies to HTTP-based connections. A local STDIO process cannot use this browser authorization flow.
Configure strict OAuth 2.1
Section titled “Configure strict OAuth 2.1”- Open Agentic → MCP Registry and select Add MCP Server.
- Select HTTP (Streamable) or SSE and enter the MCP resource URL.
- Select OAuth 2.1 (MCP 2026-07-28).
- Choose or allow one client-registration path:
- For a pre-registered client, enter its Client ID, optional Client Secret, and the exact Expected issuer that owns those credentials.
- Otherwise, leave Client ID empty. DeepIntShield uses its deployment-owned Client ID Metadata Document (CIMD) when the authorization server advertises support. Only when CIMD is not advertised does it fall back to the server’s deprecated RFC 7591 dynamic registration endpoint.
- Leave authorization, token, and registration URLs empty for discovery. If supplied, they are verification hints and must exactly match validated metadata.
- Leave scopes empty to accept the authoritative challenge or protected-resource scope set. Manually entered scopes are a verification constraint; they cannot broaden what the resource advertises.
- Select Add MCP Server, complete consent in the detached popup, and wait for finalization.
The deployment must define one stable DEEPINTSHIELD_ENCRYPTION_KEY and an
exact public APP_BASE_URL. Strict initiation is unavailable without the
encryption key. APP_BASE_URL owns the callback /api/oauth/callback and the
public CIMD /api/oauth/client-metadata.json; request Host and forwarded
headers do not choose either identifier.
Client registration priority
Section titled “Client registration priority”Strict mode implements the current MCP registration priority:
- An explicitly supplied, pre-registered client is used first. Its exact Expected issuer is mandatory.
- With no client ID, if authorization-server metadata advertises
client_id_metadata_document_supported: true, DeepIntShield uses<APP_BASE_URL>/api/oauth/client-metadata.jsonas its client ID. The public document is derived only from the trusted deployment origin, contains no credential or tenant data, is served only by an exact unauthenticated GET withno-storeandnosniff, and declarestoken_endpoint_auth_method=none. The authorization server must support that public-client method. An HTTP loopbackAPP_BASE_URLmay support an explicitly enabled local pre-registered flow, but it cannot act as the required HTTPS CIMD client ID. - If CIMD is not advertised, DeepIntShield uses RFC 7591 Dynamic Client Registration (DCR) only when a registration endpoint and a compatible token endpoint authentication method were discovered. Otherwise initiation fails.
The CIMD path never calls the DCR endpoint. The chosen provenance is persisted and shown in client details as Pre-registered client, Deployment client metadata (CIMD), or Dynamic client registration (DCR). Reauthorization must reuse the same issuer-bound provenance; it cannot silently switch methods.
These rules follow the official MCP 2026-07-28 authorization specification and client-registration guidance.
Expected issuer protects pre-registered credentials
Section titled “Expected issuer protects pre-registered credentials”A client ID or client secret is meaningful only at the authorization server where it was registered. Strict mode therefore requires Expected issuer for a pre-registered client and compares it as an exact identifier. A hostile MCP resource cannot advertise a different authorization server and receive the credential. Reauthorization also preserves this issuer binding and will not reuse credentials after an issuer change.
Use an absolute HTTPS issuer without a query, fragment, embedded user information, surrounding whitespace, or control characters. Plain HTTP is accepted only for an actual loopback host when the backend explicitly enables development loopback mode.
What strict discovery verifies
Section titled “What strict discovery verifies”Strict mode follows the MCP 2026-07-28 authorization chain:
- DeepIntShield probes the exact MCP resource with
MCP-Protocol-Version: 2026-07-28. - It requires RFC 9728 protected-resource metadata, either from a Bearer challenge or the standard path/root well-known locations.
- The metadata
resourcemust exactly equal the MCP resource used by the client. Its advertised authorization-server issuer must pass exact expected issuer binding when a pre-registered client is used. - Authorization-server metadata is read using RFC 8414 and then OpenID Connect discovery candidates. The returned issuer must exactly match the advertised issuer.
- The server must advertise authorization code, response type
code, and PKCES256. Missinggrant_types_supportedfollows the RFC default; an explicit list that excludes authorization code is rejected.
Metadata and token requests are bounded, must return the exact expected JSON media type/status, reject duplicate or ambiguously cased fields, do not follow redirects, and cannot resolve to private or reserved network addresses. The MCP transport separately binds its bearer credential to the configured scheme, host, and effective port, including for a server-advertised SSE message URL.
Production resources and OAuth endpoints must use HTTPS. For local development only, an operator may set:
DEEPINTSHIELD_OAUTH21_ALLOW_LOOPBACK=trueThis permits HTTP only on loopback. It does not permit private LAN, container, metadata-service, or arbitrary HTTP endpoints and must remain off in shared SaaS.
Authorization and token exchange
Section titled “Authorization and token exchange”The authorization request includes:
response_type=code- a cryptographically random, single-use
state code_challenge_method=S256- the exact RFC 8707 MCP
resource - the authoritative scope set, when non-empty
The callback rejects duplicate, oversized, malformed, or mixed success/error
parameters. A database compare-and-swap claims the state before issuer or code
processing, so callback replay and concurrent replicas cannot redeem the same
code twice. When the server advertises RFC 9207 authorization-response issuer
support, iss is mandatory and must exactly match; an unexpected present
issuer is always rejected.
The token endpoint receives the exact resource again and uses only an advertised supported client authentication method:
noneclient_secret_basicclient_secret_post
Token responses must be unambiguous JSON with a valid RFC 6750 Bearer token, valid bounded scope tokens, and no scope escalation. Access and refresh tokens are opaque and are never trimmed or rewritten.
Encryption and workspace isolation
Section titled “Encryption and workspace isolation”With a stable DEEPINTSHIELD_ENCRYPTION_KEY, DeepIntShield encrypts:
- client secrets;
- PKCE verifiers;
- access and refresh tokens; and
- the pending MCP client configuration needed to finish authorization on any replica.
Strict OAuth 2.1 refuses to start when encryption is unavailable. Every config, token, pending association, status read, refresh, revoke, and finalization is bound to the initiating tenant and active workspace. A sibling workspace that knows an OAuth UUID still receives no config or token.
Refresh, reauthorization, and revocation
Section titled “Refresh, reauthorization, and revocation”Live token refresh
Section titled “Live token refresh”When the provider supplies expires_in, DeepIntShield refreshes ahead of the
known expiry. A database-backed per-grant lease serializes refresh across
replicas, and the winner persists rotated credentials atomically. Public-client
refresh must rotate the refresh token. A competing lock or transient provider
failure does not silently mark an otherwise usable token expired.
The live HTTP/SSE transport resolves the current encrypted token in the exact
tenant/workspace for every outbound request. A missing, revoked, malformed, or
unavailable token stops the request before it reaches an MCP server—even one
that would otherwise accept anonymous traffic. A token with no expires_in
has an explicitly unknown local expiry; DeepIntShield does not invent a
lifetime or proactively refresh it.
Reauthorize
Section titled “Reauthorize”Open a connected MCP server and select Reauthorize. The old working grant stays active while DeepIntShield creates a new config, state, PKCE verifier, and authorization URL with the same exact issuer/resource binding. After consent, finalization atomically swaps the durable client binding and replaces the live connection. A retry after a runtime connection failure is idempotent; it does not create a second MCP client.
Finalization can return cleanup_pending: true when the superseded old grant is
already locally denied but its unreferenced row still needs cleanup. Retrying
the idempotent completion or revocation operation can finish that cleanup;
there is no autonomous cleanup worker.
For an initial flow that fails, expires, or has its popup closed, Reauthorize with fresh state preserves the encrypted pending client association. Only an explicit Cancel and revoke destroys it.
Revoke
Section titled “Revoke”Select Revoke in the client details. DeepIntShield first writes the durable
revoking state, so new normal and delegated acquisitions fail before it
disconnects a runtime or attempts the advertised RFC 7009 endpoint. A completed
cleanup removes the local token regardless of that remote result. The UI
reports remote revocation as succeeded, unsupported, or failed; none of
those values means the local credential remains usable. Remote revocation is
best effort and has no retry outbox after the local token is deleted.
On other replicas, the durable status and generation fence denies the next acquisition, and reconciliation closes passive SSE state. An already leased call is allowed to drain; revocation does not promise synchronous termination of every in-flight stream across replicas.
Deleting an OAuth MCP client also performs reference-safe credential cleanup. OAuth clients cannot be moved to a sibling workspace; create and authorize a new connection in the target workspace instead.
OAuth status
Section titled “OAuth status”The details sheet shows the secret-free OAuth state and durable metadata:
- protocol mode and
pending,exchanging,authorized,failed,expired,revoking, orrevokedstatus; - persisted client-registration provenance (pre-registered, CIMD, or DCR);
- validated issuer and whether RFC 9207 response issuer is required;
- whether remote revocation was advertised;
- token scopes; and
- token expiry only when the provider supplied a known lifetime.
It never returns token IDs, access/refresh tokens, client secrets, or PKCE verifiers.
OAuth 2.0 compatibility mode
Section titled “OAuth 2.0 compatibility mode”Select OAuth 2.0 only for an older provider that cannot complete strict MCP authorization. Compatibility mode supports authorization code with PKCE, manual/discovered endpoints, RFC 7591 dynamic registration, refresh, and local revocation. Its endpoint discovery and provider behavior are retained for existing configurations and are not equivalent to strict protected-resource metadata, expected-issuer, or callback issuer enforcement.
Register provider callback URLs as:
https://<your-deepintshield-host>/api/oauth/callbackTroubleshooting
Section titled “Troubleshooting”Strict initiation is unavailable
Section titled “Strict initiation is unavailable”- Configure one stable
DEEPINTSHIELD_ENCRYPTION_KEYon every replica. - Configure deployment-owned
APP_BASE_URLwith the public HTTPS origin. - Confirm an active workspace is selected.
Discovery is rejected
Section titled “Discovery is rejected”- Confirm the MCP resource returns or links exact RFC 9728 metadata.
- Confirm the metadata resource equals the configured connection URL.
- Confirm the advertised issuer and authorization-server metadata issuer match exactly.
- For a pre-registered client, confirm Expected issuer is the issuer that owns that client ID/secret.
- Confirm authorization code, response type
code, and PKCES256are advertised. - Remove manual endpoint/scope hints that do not exactly match metadata.
Authorization completes but the connection does not finalize
Section titled “Authorization completes but the connection does not finalize”- Keep the authorization dialog open until status becomes
authorized. - Use Retry finalization after a transient runtime connection error; the endpoint is idempotent.
- If authorization itself failed or expired, use Reauthorize with fresh state.
- Check that the OAuth config and pending MCP client still belong to the active workspace.
Refresh fails
Section titled “Refresh fails”- Confirm the provider returned a refresh token and still accepts it.
- Public clients must receive a rotated refresh token.
- Confirm the exact resource and scopes remain valid.
- Reauthorize if the provider revoked consent or no refresh token is available.
Supported boundaries and deliberate omissions
Section titled “Supported boundaries and deliberate omissions”This implementation supports pre-registered clients, a deployment-owned HTTPS CIMD public client, and deprecated RFC 7591 dynamic registration as the final fallback. It does not implement device authorization, implicit/password grants, client-credentials MCP user authorization, DPoP, mTLS-bound tokens, or authorization step-up/claims-challenge scope-union retry. It also does not implement RFC 7592 management or deletion of registrations created through DCR. An authorization server that requires an unsupported extension fails closed rather than silently switching to OAuth 2.0.