zuplo 6.70.54 → 6.70.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/mcp-gateway/auth/configuring-auth0.mdx +216 -0
- package/docs/mcp-gateway/auth/configuring-clerk.mdx +153 -0
- package/docs/mcp-gateway/auth/configuring-cognito.mdx +128 -0
- package/docs/mcp-gateway/auth/configuring-entra.mdx +134 -0
- package/docs/mcp-gateway/auth/configuring-generic-oidc.mdx +242 -0
- package/docs/mcp-gateway/auth/configuring-google.mdx +117 -0
- package/docs/mcp-gateway/auth/configuring-keycloak.mdx +125 -0
- package/docs/mcp-gateway/auth/configuring-logto.mdx +116 -0
- package/docs/mcp-gateway/auth/configuring-okta.mdx +199 -0
- package/docs/mcp-gateway/auth/configuring-onelogin.mdx +122 -0
- package/docs/mcp-gateway/auth/configuring-ping.mdx +157 -0
- package/docs/mcp-gateway/auth/configuring-workos.mdx +117 -0
- package/docs/mcp-gateway/auth/manual-oauth-testing.mdx +528 -0
- package/docs/mcp-gateway/auth/overview.mdx +314 -0
- package/docs/mcp-gateway/auth/upstream-oauth.mdx +221 -0
- package/docs/mcp-gateway/capability-filtering.mdx +162 -0
- package/docs/mcp-gateway/code-config/compatibility-dates.mdx +33 -0
- package/docs/mcp-gateway/code-config/local-development.mdx +198 -0
- package/docs/mcp-gateway/code-config/mcp-proxy-handler.mdx +186 -0
- package/docs/mcp-gateway/code-config/multi-upstream.mdx +293 -0
- package/docs/mcp-gateway/code-config/overview.mdx +210 -0
- package/docs/mcp-gateway/connect-clients/chatgpt.mdx +127 -0
- package/docs/mcp-gateway/connect-clients/claude-code.mdx +184 -0
- package/docs/mcp-gateway/connect-clients/claude-desktop.mdx +160 -0
- package/docs/mcp-gateway/connect-clients/cursor.mdx +100 -0
- package/docs/mcp-gateway/connect-clients/other-clients.mdx +207 -0
- package/docs/mcp-gateway/connect-clients/overview.mdx +137 -0
- package/docs/mcp-gateway/connect-clients/vs-code.mdx +128 -0
- package/docs/mcp-gateway/how-it-works.mdx +266 -0
- package/docs/mcp-gateway/how-to/connect-upstream-oauth.mdx +268 -0
- package/docs/mcp-gateway/how-to/curate-tools.mdx +278 -0
- package/docs/mcp-gateway/introduction.mdx +151 -0
- package/docs/mcp-gateway/observability/analytics.mdx +191 -0
- package/docs/mcp-gateway/observability/logging.mdx +191 -0
- package/docs/mcp-gateway/quickstart.mdx +266 -0
- package/docs/mcp-gateway/reference.mdx +148 -0
- package/docs/mcp-gateway/test-clients.mdx +130 -0
- package/docs/mcp-gateway/troubleshooting.mdx +228 -0
- package/docs/mcp-server/introduction.mdx +10 -0
- package/docs/mcp-server/openai-apps-sdk.mdx +12 -0
- package/docs/policies/_index.md +14 -0
- package/docs/policies/akamai-ai-firewall/schema.json +1 -0
- package/docs/policies/akamai-firewall-for-ai-inbound/schema.json +1 -0
- package/docs/policies/akamai-firewall-for-ai-outbound/schema.json +1 -0
- package/docs/policies/amberflo-metering-inbound/schema.json +1 -0
- package/docs/policies/api-key-inbound/schema.json +1 -0
- package/docs/policies/audit-log-inbound/schema.json +1 -0
- package/docs/policies/auth0-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/authzen-inbound/schema.json +1 -0
- package/docs/policies/axiomatics-authz-inbound/schema.json +1 -0
- package/docs/policies/basic-auth-inbound/schema.json +1 -0
- package/docs/policies/bot-detection-inbound/schema.json +1 -0
- package/docs/policies/brownout-inbound/schema.json +1 -0
- package/docs/policies/caching-inbound/schema.json +1 -0
- package/docs/policies/change-method-inbound/schema.json +1 -0
- package/docs/policies/clear-headers-inbound/schema.json +1 -0
- package/docs/policies/clear-headers-outbound/schema.json +1 -0
- package/docs/policies/clerk-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/cognito-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/comet-opik-tracing-inbound/schema.json +1 -0
- package/docs/policies/complex-rate-limit-inbound/schema.json +1 -0
- package/docs/policies/composite-inbound/schema.json +1 -0
- package/docs/policies/composite-outbound/schema.json +1 -0
- package/docs/policies/curity-phantom-token-inbound/schema.json +1 -0
- package/docs/policies/firebase-jwt-inbound/schema.json +1 -0
- package/docs/policies/formdata-to-json-inbound/schema.json +1 -0
- package/docs/policies/galileo-tracing-inbound/schema.json +1 -0
- package/docs/policies/geo-filter-inbound/schema.json +1 -0
- package/docs/policies/graphql-complexity-limit-inbound/schema.json +1 -0
- package/docs/policies/graphql-disable-introspection-inbound/schema.json +1 -0
- package/docs/policies/graphql-introspection-filter-outbound/schema.json +1 -0
- package/docs/policies/http-deprecation-outbound/schema.json +1 -0
- package/docs/policies/jwt-scopes-inbound/schema.json +1 -0
- package/docs/policies/ldap-auth-inbound/schema.json +1 -0
- package/docs/policies/mcp-auth0-oauth-inbound/doc.md +54 -0
- package/docs/policies/mcp-auth0-oauth-inbound/intro.md +7 -0
- package/docs/policies/mcp-auth0-oauth-inbound/schema.json +135 -0
- package/docs/policies/mcp-capability-filter-inbound/doc.md +58 -0
- package/docs/policies/mcp-capability-filter-inbound/intro.md +9 -0
- package/docs/policies/mcp-capability-filter-inbound/schema.json +212 -0
- package/docs/policies/mcp-clerk-oauth-inbound/doc.md +34 -0
- package/docs/policies/mcp-clerk-oauth-inbound/intro.md +1 -0
- package/docs/policies/mcp-clerk-oauth-inbound/schema.json +134 -0
- package/docs/policies/mcp-cognito-oauth-inbound/doc.md +52 -0
- package/docs/policies/mcp-cognito-oauth-inbound/intro.md +7 -0
- package/docs/policies/mcp-cognito-oauth-inbound/schema.json +152 -0
- package/docs/policies/mcp-entra-oauth-inbound/doc.md +51 -0
- package/docs/policies/mcp-entra-oauth-inbound/intro.md +6 -0
- package/docs/policies/mcp-entra-oauth-inbound/schema.json +131 -0
- package/docs/policies/mcp-google-oauth-inbound/doc.md +52 -0
- package/docs/policies/mcp-google-oauth-inbound/intro.md +6 -0
- package/docs/policies/mcp-google-oauth-inbound/schema.json +125 -0
- package/docs/policies/mcp-keycloak-oauth-inbound/doc.md +43 -0
- package/docs/policies/mcp-keycloak-oauth-inbound/intro.md +2 -0
- package/docs/policies/mcp-keycloak-oauth-inbound/schema.json +140 -0
- package/docs/policies/mcp-logto-oauth-inbound/doc.md +52 -0
- package/docs/policies/mcp-logto-oauth-inbound/intro.md +6 -0
- package/docs/policies/mcp-logto-oauth-inbound/schema.json +131 -0
- package/docs/policies/mcp-oauth-inbound/doc.md +70 -0
- package/docs/policies/mcp-oauth-inbound/intro.md +11 -0
- package/docs/policies/mcp-oauth-inbound/schema.json +177 -0
- package/docs/policies/mcp-okta-oauth-inbound/doc.md +61 -0
- package/docs/policies/mcp-okta-oauth-inbound/intro.md +7 -0
- package/docs/policies/mcp-okta-oauth-inbound/schema.json +137 -0
- package/docs/policies/mcp-onelogin-oauth-inbound/doc.md +50 -0
- package/docs/policies/mcp-onelogin-oauth-inbound/intro.md +6 -0
- package/docs/policies/mcp-onelogin-oauth-inbound/schema.json +131 -0
- package/docs/policies/mcp-ping-oauth-inbound/doc.md +80 -0
- package/docs/policies/mcp-ping-oauth-inbound/intro.md +7 -0
- package/docs/policies/mcp-ping-oauth-inbound/schema.json +151 -0
- package/docs/policies/mcp-token-exchange-inbound/doc.md +135 -0
- package/docs/policies/mcp-token-exchange-inbound/intro.md +6 -0
- package/docs/policies/mcp-token-exchange-inbound/schema.json +134 -0
- package/docs/policies/mcp-workos-oauth-inbound/doc.md +50 -0
- package/docs/policies/mcp-workos-oauth-inbound/intro.md +6 -0
- package/docs/policies/mcp-workos-oauth-inbound/schema.json +125 -0
- package/docs/policies/mock-api-inbound/schema.json +1 -0
- package/docs/policies/moesif-inbound/schema.json +1 -0
- package/docs/policies/monetization-inbound/schema.json +1 -0
- package/docs/policies/mtls-auth-inbound/schema.json +1 -0
- package/docs/policies/okta-fga-authz-inbound/schema.json +1 -0
- package/docs/policies/okta-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/open-id-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/openfga-authz-inbound/schema.json +1 -0
- package/docs/policies/openmeter-inbound/schema.json +1 -0
- package/docs/policies/prompt-injection-outbound/schema.json +1 -0
- package/docs/policies/propel-auth-jwt-inbound/schema.json +1 -0
- package/docs/policies/query-param-to-header-inbound/schema.json +1 -0
- package/docs/policies/quota-inbound/schema.json +1 -0
- package/docs/policies/rate-limit-inbound/schema.json +1 -0
- package/docs/policies/readme-metrics-inbound/schema.json +1 -0
- package/docs/policies/remove-headers-inbound/schema.json +1 -0
- package/docs/policies/remove-headers-outbound/schema.json +1 -0
- package/docs/policies/remove-query-params-inbound/schema.json +1 -0
- package/docs/policies/replace-string-outbound/schema.json +1 -0
- package/docs/policies/request-size-limit-inbound/schema.json +1 -0
- package/docs/policies/request-validation-inbound/schema.json +1 -0
- package/docs/policies/require-origin-inbound/schema.json +1 -0
- package/docs/policies/secret-masking-outbound/schema.json +1 -0
- package/docs/policies/semantic-cache-inbound/schema.json +1 -0
- package/docs/policies/set-body-inbound/schema.json +1 -0
- package/docs/policies/set-headers-inbound/schema.json +1 -0
- package/docs/policies/set-headers-outbound/schema.json +1 -0
- package/docs/policies/set-query-params-inbound/schema.json +1 -0
- package/docs/policies/set-status-outbound/schema.json +1 -0
- package/docs/policies/set-upstream-api-key-inbound/schema.json +1 -0
- package/docs/policies/sleep-inbound/schema.json +1 -0
- package/docs/policies/stripe-webhook-verification-inbound/schema.json +1 -0
- package/docs/policies/supabase-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/upstream-azure-ad-service-auth-inbound/schema.json +1 -0
- package/docs/policies/upstream-firebase-admin-auth-inbound/schema.json +1 -0
- package/docs/policies/upstream-firebase-user-auth-inbound/schema.json +1 -0
- package/docs/policies/upstream-gcp-federated-auth-inbound/schema.json +1 -0
- package/docs/policies/upstream-gcp-jwt-inbound/schema.json +1 -0
- package/docs/policies/upstream-gcp-service-auth-inbound/schema.json +1 -0
- package/docs/policies/upstream-zuplo-jwt-auth-inbound/schema.json +1 -0
- package/docs/policies/validate-json-schema-inbound/schema.json +1 -0
- package/docs/policies/web-bot-auth-inbound/schema.json +1 -0
- package/docs/policies/xml-to-json-outbound/schema.json +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Configuring Auth0"
|
|
3
|
+
sidebar_label: "Auth0"
|
|
4
|
+
description:
|
|
5
|
+
Configure Auth0 to back the MCP Gateway's downstream OAuth using the
|
|
6
|
+
mcp-auth0-oauth-inbound policy. Covers tenant setup, application
|
|
7
|
+
configuration, and wiring the policy in your gateway project.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
The MCP Gateway can use Auth0 as the identity provider behind its downstream
|
|
11
|
+
OAuth flow. The `mcp-auth0-oauth-inbound` policy is an Auth0-friendly wrapper
|
|
12
|
+
around the generic `mcp-oauth-inbound` policy: provide your Auth0 domain, a
|
|
13
|
+
client ID, and a client secret, and the policy derives the OIDC issuer, JWKS
|
|
14
|
+
URL, and Auth0 authorize and token URLs for you.
|
|
15
|
+
|
|
16
|
+
This guide walks through the Auth0 dashboard setup, then shows how to wire the
|
|
17
|
+
policy into your gateway project. Read the
|
|
18
|
+
[authentication overview](./overview.mdx) first for the two-layer model and the
|
|
19
|
+
role each policy plays.
|
|
20
|
+
|
|
21
|
+
:::note
|
|
22
|
+
|
|
23
|
+
This guide assumes you have a working Auth0 tenant. The
|
|
24
|
+
[Auth0 MCP client registration guide](https://auth0.com/ai/docs/mcp/guides/registering-your-mcp-client-application)
|
|
25
|
+
is the authoritative source for Auth0-side configuration.
|
|
26
|
+
|
|
27
|
+
:::
|
|
28
|
+
|
|
29
|
+
Most projects only need three options: `auth0Domain`, `clientId`, and
|
|
30
|
+
`clientSecret`. `audience`, `scope`, and the TTL options are all optional.
|
|
31
|
+
|
|
32
|
+
:::caution
|
|
33
|
+
|
|
34
|
+
`auth0Domain` is a **bare hostname**, not a URL. Use `my-tenant.us.auth0.com`,
|
|
35
|
+
not `https://my-tenant.us.auth0.com/`.
|
|
36
|
+
|
|
37
|
+
:::
|
|
38
|
+
|
|
39
|
+
## Set up the Auth0 tenant
|
|
40
|
+
|
|
41
|
+
The MCP Gateway acts as an OAuth 2.1 authorization server in front of Auth0.
|
|
42
|
+
Auth0 handles browser login and identity; the gateway issues its own access
|
|
43
|
+
tokens that bind to MCP routes. The Auth0 application you create represents the
|
|
44
|
+
**gateway's identity** against Auth0, not the MCP client.
|
|
45
|
+
|
|
46
|
+
### Create an Auth0 application
|
|
47
|
+
|
|
48
|
+
1. In the Auth0 Dashboard, open **Applications > Applications** and click
|
|
49
|
+
**Create Application**.
|
|
50
|
+
2. Set a name (for example, `Zuplo MCP Gateway`).
|
|
51
|
+
3. Choose **Regular Web Application** as the application type and click
|
|
52
|
+
**Create**.
|
|
53
|
+
4. On the **Settings** tab, note the **Domain**, **Client ID**, and **Client
|
|
54
|
+
Secret**. You'll wire these into the policy in the next section.
|
|
55
|
+
|
|
56
|
+
### Configure callback and origin URLs
|
|
57
|
+
|
|
58
|
+
The gateway completes browser login by redirecting back to its own
|
|
59
|
+
`/oauth/callback` endpoint, so Auth0 needs that URL on its allow-list.
|
|
60
|
+
|
|
61
|
+
On the same **Settings** tab:
|
|
62
|
+
|
|
63
|
+
1. Set **Allowed Callback URLs** to your gateway's
|
|
64
|
+
`https://<gateway-host>/oauth/callback`. For local development against
|
|
65
|
+
`zuplo dev`, add `http://localhost:9000/oauth/callback` as well.
|
|
66
|
+
2. Set **Allowed Web Origins** to the gateway origin `https://<gateway-host>`
|
|
67
|
+
(plus `http://localhost:9000` for local dev).
|
|
68
|
+
3. Save changes.
|
|
69
|
+
|
|
70
|
+
### Optional: Set an audience
|
|
71
|
+
|
|
72
|
+
If you want Auth0 to issue identity-bound API access tokens (for example, to
|
|
73
|
+
validate Auth0-issued tokens against a specific resource server), create an API
|
|
74
|
+
under **Applications > APIs** with an identifier like
|
|
75
|
+
`https://gateway.example.com` and pass that identifier as the `audience` option
|
|
76
|
+
on the policy. When omitted, Auth0 acts only as the browser identity layer and
|
|
77
|
+
the gateway alone owns the OAuth grant the MCP client receives.
|
|
78
|
+
|
|
79
|
+
### Connections and dynamic client registration
|
|
80
|
+
|
|
81
|
+
The downstream OAuth flow only requires Auth0 to authenticate the user and
|
|
82
|
+
return an ID token. CIMD and DCR on Auth0's side concern the **upstream MCP
|
|
83
|
+
server's** trust of clients, not the gateway's trust of Auth0. If you also
|
|
84
|
+
configure Auth0 itself as an upstream MCP authorization provider (rare), follow
|
|
85
|
+
Auth0's own guide for
|
|
86
|
+
[enabling CIMD](https://auth0.com/ai/docs/mcp/guides/registering-your-mcp-client-application/manual-cimd-registration)
|
|
87
|
+
or
|
|
88
|
+
[enabling DCR](https://auth0.com/ai/docs/mcp/guides/registering-your-mcp-client-application/dynamic-client-registration).
|
|
89
|
+
|
|
90
|
+
## Wire the policy into the gateway
|
|
91
|
+
|
|
92
|
+
Add the policy to `config/policies.json`:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"name": "auth0-managed-oauth",
|
|
97
|
+
"policyType": "mcp-auth0-oauth-inbound",
|
|
98
|
+
"handler": {
|
|
99
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
100
|
+
"export": "McpAuth0OAuthInboundPolicy",
|
|
101
|
+
"options": {
|
|
102
|
+
"auth0Domain": "$env(AUTH0_DOMAIN)",
|
|
103
|
+
"clientId": "$env(AUTH0_CLIENT_ID)",
|
|
104
|
+
"clientSecret": "$env(AUTH0_CLIENT_SECRET)"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Set the three environment variables in your Zuplo project's environment
|
|
111
|
+
configuration. `AUTH0_DOMAIN` is the bare hostname; the secret values belong in
|
|
112
|
+
the project secret store.
|
|
113
|
+
|
|
114
|
+
Attach the policy to each MCP route in `config/routes.oas.json`:
|
|
115
|
+
|
|
116
|
+
```jsonc
|
|
117
|
+
{
|
|
118
|
+
"paths": {
|
|
119
|
+
"/mcp/linear": {
|
|
120
|
+
"get,post": {
|
|
121
|
+
"operationId": "linear-mcp-server",
|
|
122
|
+
"x-zuplo-route": {
|
|
123
|
+
"corsPolicy": "none",
|
|
124
|
+
"handler": {
|
|
125
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
126
|
+
"export": "McpProxyHandler",
|
|
127
|
+
"options": {
|
|
128
|
+
"rewritePattern": "https://mcp.linear.app/mcp",
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
"policies": {
|
|
132
|
+
"inbound": ["auth0-managed-oauth", "mcp-token-exchange-linear"],
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Finally, register the gateway plugin in `modules/zuplo.runtime.ts` so the
|
|
142
|
+
runtime registers the OAuth endpoints automatically:
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
import { RuntimeExtensions } from "@zuplo/runtime";
|
|
146
|
+
import { McpGatewayPlugin } from "@zuplo/runtime/mcp-gateway";
|
|
147
|
+
|
|
148
|
+
export function runtimeInit(runtime: RuntimeExtensions) {
|
|
149
|
+
runtime.addPlugin(new McpGatewayPlugin());
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
One MCP OAuth policy serves every MCP route in the project — there's no need to
|
|
154
|
+
declare it more than once. Attaching the same policy by name to each route is
|
|
155
|
+
the canonical pattern.
|
|
156
|
+
|
|
157
|
+
## Full options reference
|
|
158
|
+
|
|
159
|
+
`mcp-auth0-oauth-inbound` has three required options and a few optional
|
|
160
|
+
overrides. The complete schema is documented on the policy reference page; the
|
|
161
|
+
fields you'll touch most often are:
|
|
162
|
+
|
|
163
|
+
| Option | Required | Default | Notes |
|
|
164
|
+
| ----------------------------------------- | -------- | ---------------------- | ------------------------------------------------------------------------------------------ |
|
|
165
|
+
| `auth0Domain` | yes | — | Bare hostname (`my-tenant.us.auth0.com`). No scheme, must contain a dot. |
|
|
166
|
+
| `clientId` | yes | — | Auth0 application client ID. |
|
|
167
|
+
| `clientSecret` | yes | — | Auth0 application client secret. Use `$env(...)` to source from a secret. |
|
|
168
|
+
| `audience` | no | unset | Optional Auth0 API identifier. Sent as the `?audience=` parameter to Auth0's `/authorize`. |
|
|
169
|
+
| `scope` | no | `openid profile email` | OIDC scopes requested during browser login. |
|
|
170
|
+
| `gateway.accessTokenTtlSeconds` | no | `900` | Gateway-issued access token lifetime. |
|
|
171
|
+
| `gateway.refreshTokenTtlSeconds` | no | long-lived | Gateway-issued refresh token lifetime. Override only if you need to shorten sessions. |
|
|
172
|
+
| `gateway.cimdEnabled` | no | `true` | Advertise CIMD support in AS metadata. |
|
|
173
|
+
| `browserLoginOverrides.sessionTtlSeconds` | no | `28800` | Browser session cookie lifetime (8 hours). |
|
|
174
|
+
| `browserLoginOverrides.stateTtlSeconds` | no | `900` | Browser-login state record lifetime. |
|
|
175
|
+
| `browserLoginOverrides.remoteTimeoutMs` | no | `10000` | Outbound timeout to Auth0 (token exchange, JWKS fetch). |
|
|
176
|
+
|
|
177
|
+
## Test the configuration
|
|
178
|
+
|
|
179
|
+
The fastest sanity check is to try connecting an MCP client:
|
|
180
|
+
|
|
181
|
+
1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
|
|
182
|
+
2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes on the
|
|
183
|
+
gateway.
|
|
184
|
+
3. The client should redirect you to Auth0's login page. After login, the
|
|
185
|
+
gateway's consent screen renders. Approve it.
|
|
186
|
+
4. The client receives an access token and can call `tools/list`.
|
|
187
|
+
|
|
188
|
+
If something fails partway through, walk the flow manually using the
|
|
189
|
+
[manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
|
|
190
|
+
endpoint with `curl` so you can see the raw responses.
|
|
191
|
+
|
|
192
|
+
## Common issues
|
|
193
|
+
|
|
194
|
+
- **"Invalid Auth0 domain" at boot.** The `auth0Domain` value includes a scheme
|
|
195
|
+
prefix or doesn't contain a dot. Use `my-tenant.us.auth0.com`.
|
|
196
|
+
- **Browser login redirects but the callback fails.** The
|
|
197
|
+
`https://<gateway-host>/oauth/callback` URL isn't on the **Allowed Callback
|
|
198
|
+
URLs** list for the Auth0 application.
|
|
199
|
+
- **Token endpoint returns `invalid_audience`.** The MCP client is reusing a
|
|
200
|
+
token bound to a different route. Each gateway-issued token binds to one
|
|
201
|
+
`operationId`; the client must obtain a separate token per route.
|
|
202
|
+
- **Issuer in AS metadata is wrong.** The gateway derives its issuer from the
|
|
203
|
+
incoming request origin. Check that your custom domain or proxy forwards the
|
|
204
|
+
correct `Host` or `X-Forwarded-Host` header. See
|
|
205
|
+
[Troubleshooting](../troubleshooting.mdx).
|
|
206
|
+
- **MCP client can't discover the AS.** Confirm the `mcp-auth0-oauth-inbound`
|
|
207
|
+
policy is attached to the route in `routes.oas.json` and that the
|
|
208
|
+
`McpGatewayPlugin` is registered in `modules/zuplo.runtime.ts`. The internal
|
|
209
|
+
OAuth endpoints register only when both are present.
|
|
210
|
+
|
|
211
|
+
## Related
|
|
212
|
+
|
|
213
|
+
- [Authentication overview](./overview.mdx)
|
|
214
|
+
- `mcp-auth0-oauth-inbound` policy reference
|
|
215
|
+
- [Configuring Okta or any other OIDC IdP](./configuring-okta.mdx)
|
|
216
|
+
- [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Configuring Clerk"
|
|
3
|
+
sidebar_label: "Clerk"
|
|
4
|
+
description:
|
|
5
|
+
Configure Clerk to back the MCP Gateway's downstream OAuth using the
|
|
6
|
+
mcp-clerk-oauth-inbound policy. Covers OAuth application setup and wiring the
|
|
7
|
+
policy in your gateway project.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
The MCP Gateway can use [Clerk](https://clerk.com/) as the identity provider
|
|
11
|
+
behind its downstream OAuth flow. The `mcp-clerk-oauth-inbound` policy is a
|
|
12
|
+
Clerk-friendly wrapper around the generic `mcp-oauth-inbound` policy: provide
|
|
13
|
+
your Clerk Frontend API URL, a client ID, and a client secret, and the policy
|
|
14
|
+
derives the OIDC issuer, JWKS URL, and authorize and token URLs for you.
|
|
15
|
+
|
|
16
|
+
This guide walks through the Clerk dashboard setup, then wires the policy into a
|
|
17
|
+
gateway project. Read the [authentication overview](./overview.mdx) first for
|
|
18
|
+
the two-layer OAuth model.
|
|
19
|
+
|
|
20
|
+
## Set up Clerk
|
|
21
|
+
|
|
22
|
+
The MCP Gateway acts as an OAuth 2.1 authorization server in front of Clerk.
|
|
23
|
+
Clerk handles browser login; the gateway issues its own access tokens that bind
|
|
24
|
+
to MCP routes.
|
|
25
|
+
|
|
26
|
+
### Create an OAuth application
|
|
27
|
+
|
|
28
|
+
1. In the Clerk Dashboard, switch to the instance you want the gateway to use,
|
|
29
|
+
then open **Configure → OAuth Applications**.
|
|
30
|
+
2. Click **Add OAuth application**.
|
|
31
|
+
3. Give the application a name (for example, `Zuplo MCP Gateway`).
|
|
32
|
+
4. Set **Redirect URIs** to `https://<gateway-host>/oauth/callback`. Add
|
|
33
|
+
`http://localhost:9000/oauth/callback` for local development with
|
|
34
|
+
`zuplo dev`.
|
|
35
|
+
5. Select the OIDC scopes the gateway needs — `openid`, `profile`, and `email`
|
|
36
|
+
are enough.
|
|
37
|
+
6. Click **Save**.
|
|
38
|
+
|
|
39
|
+
Note the **Client ID** and **Client Secret** from the application's detail page.
|
|
40
|
+
You'll wire these into the policy in the next section.
|
|
41
|
+
|
|
42
|
+
### Find the Frontend API URL
|
|
43
|
+
|
|
44
|
+
Open **Configure → Domains** in the Clerk Dashboard. The **Frontend API URL** is
|
|
45
|
+
shown at the top — it looks like `https://verb-noun-00.clerk.accounts.dev` on
|
|
46
|
+
development instances or `https://clerk.example.com` on production instances
|
|
47
|
+
with a custom domain. Copy the origin (no trailing path).
|
|
48
|
+
|
|
49
|
+
## Wire the policy into the gateway
|
|
50
|
+
|
|
51
|
+
Add the policy to `config/policies.json`:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"name": "clerk-managed-oauth",
|
|
56
|
+
"policyType": "mcp-clerk-oauth-inbound",
|
|
57
|
+
"handler": {
|
|
58
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
59
|
+
"export": "McpClerkOAuthInboundPolicy",
|
|
60
|
+
"options": {
|
|
61
|
+
"frontendApiUrl": "$env(CLERK_FRONTEND_API_URL)",
|
|
62
|
+
"clientId": "$env(CLERK_CLIENT_ID)",
|
|
63
|
+
"clientSecret": "$env(CLERK_CLIENT_SECRET)"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
:::caution
|
|
70
|
+
|
|
71
|
+
`frontendApiUrl` is the origin only. Don't include a path, query string, or
|
|
72
|
+
fragment — the policy fails at boot if any of those are present.
|
|
73
|
+
|
|
74
|
+
:::
|
|
75
|
+
|
|
76
|
+
Set the three environment variables in your project's environment configuration.
|
|
77
|
+
`CLERK_FRONTEND_API_URL` goes in plain config; the secret values belong in the
|
|
78
|
+
project secret store.
|
|
79
|
+
|
|
80
|
+
Attach the policy to each MCP route in `config/routes.oas.json`:
|
|
81
|
+
|
|
82
|
+
```jsonc
|
|
83
|
+
{
|
|
84
|
+
"paths": {
|
|
85
|
+
"/mcp/linear-v1": {
|
|
86
|
+
"get,post": {
|
|
87
|
+
"operationId": "linear-mcp-server",
|
|
88
|
+
"x-zuplo-route": {
|
|
89
|
+
"corsPolicy": "none",
|
|
90
|
+
"handler": {
|
|
91
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
92
|
+
"export": "McpProxyHandler",
|
|
93
|
+
"options": {
|
|
94
|
+
"rewritePattern": "https://mcp.linear.app/mcp",
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
"policies": {
|
|
98
|
+
"inbound": ["clerk-managed-oauth", "mcp-token-exchange-linear"],
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Register the gateway plugin in `modules/zuplo.runtime.ts`:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import { RuntimeExtensions } from "@zuplo/runtime";
|
|
111
|
+
import { McpGatewayPlugin } from "@zuplo/runtime/mcp-gateway";
|
|
112
|
+
|
|
113
|
+
export function runtimeInit(runtime: RuntimeExtensions) {
|
|
114
|
+
runtime.addPlugin(new McpGatewayPlugin());
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## What the wrapper derives
|
|
119
|
+
|
|
120
|
+
| Generic field | Derived value |
|
|
121
|
+
| ----------------------- | ---------------------------------------- |
|
|
122
|
+
| `oidc.issuer` | `{frontendApiUrl}` |
|
|
123
|
+
| `oidc.jwksUrl` | `{frontendApiUrl}/.well-known/jwks.json` |
|
|
124
|
+
| `browserLogin.url` | `{frontendApiUrl}/oauth/authorize` |
|
|
125
|
+
| `browserLogin.tokenUrl` | `{frontendApiUrl}/oauth/token` |
|
|
126
|
+
|
|
127
|
+
## Test the configuration
|
|
128
|
+
|
|
129
|
+
The fastest sanity check is to connect an MCP client:
|
|
130
|
+
|
|
131
|
+
1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
|
|
132
|
+
2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
|
|
133
|
+
3. The client should redirect you to Clerk's login page. After login, the
|
|
134
|
+
gateway's consent screen renders. Approve it.
|
|
135
|
+
4. The client receives an access token and can call `tools/list`.
|
|
136
|
+
|
|
137
|
+
If something fails partway through, walk the flow manually using the
|
|
138
|
+
[manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
|
|
139
|
+
endpoint with `curl` so you can see the raw responses.
|
|
140
|
+
|
|
141
|
+
## Common issues
|
|
142
|
+
|
|
143
|
+
- **The policy rejects `frontendApiUrl` at boot.** The value includes a path,
|
|
144
|
+
query string, or fragment. Use only the origin (`https://clerk.example.com`).
|
|
145
|
+
- **Browser login redirects but the callback fails.** The
|
|
146
|
+
`https://<gateway-host>/oauth/callback` URL isn't on the OAuth application's
|
|
147
|
+
redirect URIs allow-list in Clerk.
|
|
148
|
+
|
|
149
|
+
## Related
|
|
150
|
+
|
|
151
|
+
- [Authentication overview](./overview.mdx)
|
|
152
|
+
- [Configuring a generic OIDC provider](./configuring-generic-oidc.mdx)
|
|
153
|
+
- [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Configuring Amazon Cognito"
|
|
3
|
+
sidebar_label: "Amazon Cognito"
|
|
4
|
+
description:
|
|
5
|
+
Configure Amazon Cognito to back the MCP Gateway's downstream OAuth using the
|
|
6
|
+
mcp-cognito-oauth-inbound policy. Covers user pool setup, hosted UI domain,
|
|
7
|
+
and wiring the policy in your gateway project.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
The MCP Gateway can use Amazon Cognito as the identity provider behind its
|
|
11
|
+
downstream OAuth flow. The `mcp-cognito-oauth-inbound` policy is a
|
|
12
|
+
Cognito-friendly wrapper around the generic `mcp-oauth-inbound` policy: provide
|
|
13
|
+
your AWS region, user pool ID, hosted UI domain, client ID, and client secret,
|
|
14
|
+
and the policy derives the OIDC issuer, JWKS URL, and authorize and token URLs
|
|
15
|
+
for you.
|
|
16
|
+
|
|
17
|
+
This guide walks through the Cognito user pool setup, then wires the policy into
|
|
18
|
+
a gateway project. Read the [authentication overview](./overview.mdx) first for
|
|
19
|
+
the two-layer OAuth model.
|
|
20
|
+
|
|
21
|
+
:::note
|
|
22
|
+
|
|
23
|
+
Cognito splits OIDC across two domains: discovery and JWKS are served from the
|
|
24
|
+
Cognito IDP service domain (`cognito-idp.{region}.amazonaws.com/{userPoolId}`),
|
|
25
|
+
while browser login is served from the **user pool hosted UI domain**. The
|
|
26
|
+
wrapper handles both.
|
|
27
|
+
|
|
28
|
+
:::
|
|
29
|
+
|
|
30
|
+
## Set up Cognito
|
|
31
|
+
|
|
32
|
+
### Create or pick a user pool
|
|
33
|
+
|
|
34
|
+
1. In the AWS Cognito console, open **User pools** and either pick an existing
|
|
35
|
+
pool or create a new one. Note the **User pool ID** (it looks like
|
|
36
|
+
`us-east-1_AbCdEf123`).
|
|
37
|
+
2. Under **App integration**, set up a **hosted UI domain**. You can use a
|
|
38
|
+
Cognito-prefix domain like `my-pool.auth.us-east-1.amazoncognito.com` or a
|
|
39
|
+
custom domain like `auth.example.com`. The wrapper takes only the host — no
|
|
40
|
+
scheme, no path.
|
|
41
|
+
|
|
42
|
+
### Create an app client
|
|
43
|
+
|
|
44
|
+
1. Under **App integration → App clients**, click **Create app client**.
|
|
45
|
+
2. Choose **Confidential client**. The client must have a client secret — the
|
|
46
|
+
gateway needs it for the federated token exchange.
|
|
47
|
+
3. Set **Allowed callback URLs** to `https://<gateway-host>/oauth/callback`. Add
|
|
48
|
+
`http://localhost:9000/oauth/callback` for local development.
|
|
49
|
+
4. Enable **Authorization code grant** under allowed OAuth flows.
|
|
50
|
+
5. Enable the OIDC scopes the gateway needs — `openid`, `profile`, and `email`.
|
|
51
|
+
6. Click **Create app client**.
|
|
52
|
+
|
|
53
|
+
Note the **Client ID** and **Client Secret** from the app client's detail page.
|
|
54
|
+
|
|
55
|
+
## Wire the policy into the gateway
|
|
56
|
+
|
|
57
|
+
Add the policy to `config/policies.json`:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"name": "cognito-managed-oauth",
|
|
62
|
+
"policyType": "mcp-cognito-oauth-inbound",
|
|
63
|
+
"handler": {
|
|
64
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
65
|
+
"export": "McpCognitoOAuthInboundPolicy",
|
|
66
|
+
"options": {
|
|
67
|
+
"awsRegion": "us-east-1",
|
|
68
|
+
"userPoolId": "$env(COGNITO_USER_POOL_ID)",
|
|
69
|
+
"userPoolDomain": "$env(COGNITO_USER_POOL_DOMAIN)",
|
|
70
|
+
"clientId": "$env(COGNITO_CLIENT_ID)",
|
|
71
|
+
"clientSecret": "$env(COGNITO_CLIENT_SECRET)"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
:::caution
|
|
78
|
+
|
|
79
|
+
`userPoolDomain` is the hosted UI host only — no `https://`, no trailing slash,
|
|
80
|
+
no path. The policy fails at boot if any of those are present.
|
|
81
|
+
|
|
82
|
+
:::
|
|
83
|
+
|
|
84
|
+
Attach the policy to each MCP route in `config/routes.oas.json` and register the
|
|
85
|
+
gateway plugin in `modules/zuplo.runtime.ts` (see
|
|
86
|
+
[Configuring Auth0](./configuring-auth0.mdx#wire-the-policy-into-the-gateway)
|
|
87
|
+
for the route and plugin patterns — they're identical across all wrappers).
|
|
88
|
+
|
|
89
|
+
## What the wrapper derives
|
|
90
|
+
|
|
91
|
+
| Generic field | Derived value |
|
|
92
|
+
| ----------------------- | ---------------------------------------------------------------------------------- |
|
|
93
|
+
| `oidc.issuer` | `https://cognito-idp.{awsRegion}.amazonaws.com/{userPoolId}` |
|
|
94
|
+
| `oidc.jwksUrl` | `https://cognito-idp.{awsRegion}.amazonaws.com/{userPoolId}/.well-known/jwks.json` |
|
|
95
|
+
| `browserLogin.url` | `https://{userPoolDomain}/oauth2/authorize` |
|
|
96
|
+
| `browserLogin.tokenUrl` | `https://{userPoolDomain}/oauth2/token` |
|
|
97
|
+
|
|
98
|
+
## Test the configuration
|
|
99
|
+
|
|
100
|
+
The fastest sanity check is to connect an MCP client:
|
|
101
|
+
|
|
102
|
+
1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
|
|
103
|
+
2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
|
|
104
|
+
3. The client should redirect you to the Cognito hosted UI sign-in page. After
|
|
105
|
+
login, the gateway's consent screen renders. Approve it.
|
|
106
|
+
4. The client receives an access token and can call `tools/list`.
|
|
107
|
+
|
|
108
|
+
If something fails partway through, walk the flow manually using the
|
|
109
|
+
[manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
|
|
110
|
+
endpoint with `curl` so you can see the raw responses.
|
|
111
|
+
|
|
112
|
+
## Common issues
|
|
113
|
+
|
|
114
|
+
- **The policy rejects `userPoolDomain` at boot.** The value includes
|
|
115
|
+
`https://`, a trailing slash, or an OAuth path. Strip those — use only
|
|
116
|
+
`auth.example.com` or `my-pool.auth.us-east-1.amazoncognito.com`.
|
|
117
|
+
- **Browser login lands on a Cognito error page.** The callback URL on the app
|
|
118
|
+
client doesn't match. Set it to `https://<gateway-host>/oauth/callback`
|
|
119
|
+
exactly.
|
|
120
|
+
- **`invalid_client` from Cognito's token endpoint.** The app client doesn't
|
|
121
|
+
have a client secret, or the secret value doesn't match. Cognito confidential
|
|
122
|
+
clients require both ID and secret.
|
|
123
|
+
|
|
124
|
+
## Related
|
|
125
|
+
|
|
126
|
+
- [Authentication overview](./overview.mdx)
|
|
127
|
+
- [Configuring a generic OIDC provider](./configuring-generic-oidc.mdx)
|
|
128
|
+
- [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Configuring Microsoft Entra ID"
|
|
3
|
+
sidebar_label: "Microsoft Entra"
|
|
4
|
+
description:
|
|
5
|
+
Configure Microsoft Entra ID to back the MCP Gateway's downstream OAuth using
|
|
6
|
+
the mcp-entra-oauth-inbound policy. Covers app registration and wiring the
|
|
7
|
+
policy in your gateway project.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
The MCP Gateway can use Microsoft Entra ID (formerly Azure AD) as the identity
|
|
11
|
+
provider behind its downstream OAuth flow. The `mcp-entra-oauth-inbound` policy
|
|
12
|
+
is an Entra-friendly wrapper around the generic `mcp-oauth-inbound` policy:
|
|
13
|
+
provide your Entra tenant UUID, a client ID, and a client secret, and the policy
|
|
14
|
+
derives the v2 OIDC issuer, JWKS URL, and authorize and token URLs for you.
|
|
15
|
+
|
|
16
|
+
This guide walks through the Microsoft Entra admin center setup, then wires the
|
|
17
|
+
policy into a gateway project. Read the
|
|
18
|
+
[authentication overview](./overview.mdx) first for the two-layer OAuth model.
|
|
19
|
+
|
|
20
|
+
:::caution
|
|
21
|
+
|
|
22
|
+
This policy is **single-tenant**. The multi-tenant aliases `common`,
|
|
23
|
+
`organizations`, and `consumers` are not supported because Entra's issuer claim
|
|
24
|
+
is tenant-specific and the gateway enforces an exact issuer match. Use a real
|
|
25
|
+
tenant UUID.
|
|
26
|
+
|
|
27
|
+
:::
|
|
28
|
+
|
|
29
|
+
## Set up Microsoft Entra
|
|
30
|
+
|
|
31
|
+
The MCP Gateway acts as an OAuth 2.1 authorization server in front of Entra.
|
|
32
|
+
Entra handles browser login; the gateway issues its own access tokens that bind
|
|
33
|
+
to MCP routes.
|
|
34
|
+
|
|
35
|
+
### Register an application
|
|
36
|
+
|
|
37
|
+
1. In the Microsoft Entra admin center, open **Identity → Applications → App
|
|
38
|
+
registrations** and click **New registration**.
|
|
39
|
+
2. Give the application a name (for example, `Zuplo MCP Gateway`).
|
|
40
|
+
3. Under **Supported account types**, choose **Accounts in this organizational
|
|
41
|
+
directory only (single tenant)**. The wrapper does not support multi-tenant
|
|
42
|
+
modes.
|
|
43
|
+
4. Under **Redirect URI**, choose **Web** and set the value to
|
|
44
|
+
`https://<gateway-host>/oauth/callback`. Click **Register**.
|
|
45
|
+
5. On the application's **Overview** page, note the **Application (client) ID**
|
|
46
|
+
and the **Directory (tenant) ID**. Both are UUIDs.
|
|
47
|
+
|
|
48
|
+
### Add a client secret
|
|
49
|
+
|
|
50
|
+
1. Open **Certificates & secrets** on the application and click **New client
|
|
51
|
+
secret**.
|
|
52
|
+
2. Set a description and an expiration window, then click **Add**.
|
|
53
|
+
3. Copy the secret **Value** immediately — Entra only shows it once.
|
|
54
|
+
|
|
55
|
+
### Add the local development redirect URI
|
|
56
|
+
|
|
57
|
+
1. Open **Authentication** on the application.
|
|
58
|
+
2. Add `http://localhost:9000/oauth/callback` under **Web → Redirect URIs**.
|
|
59
|
+
3. Save.
|
|
60
|
+
|
|
61
|
+
### Optional: restrict access
|
|
62
|
+
|
|
63
|
+
By default any user in the tenant can sign in. To restrict access to specific
|
|
64
|
+
groups, open **Enterprise applications**, find the same application, and use
|
|
65
|
+
**Properties → Assignment required** plus **Users and groups** assignments.
|
|
66
|
+
|
|
67
|
+
## Wire the policy into the gateway
|
|
68
|
+
|
|
69
|
+
Add the policy to `config/policies.json`:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"name": "entra-managed-oauth",
|
|
74
|
+
"policyType": "mcp-entra-oauth-inbound",
|
|
75
|
+
"handler": {
|
|
76
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
77
|
+
"export": "McpEntraOAuthInboundPolicy",
|
|
78
|
+
"options": {
|
|
79
|
+
"tenantId": "$env(ENTRA_TENANT_ID)",
|
|
80
|
+
"clientId": "$env(ENTRA_CLIENT_ID)",
|
|
81
|
+
"clientSecret": "$env(ENTRA_CLIENT_SECRET)"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Set the three environment variables in your project's environment configuration.
|
|
88
|
+
The secret values belong in the project secret store.
|
|
89
|
+
|
|
90
|
+
Attach the policy to each MCP route in `config/routes.oas.json` and register the
|
|
91
|
+
gateway plugin in `modules/zuplo.runtime.ts` (see
|
|
92
|
+
[Configuring Auth0](./configuring-auth0.mdx#wire-the-policy-into-the-gateway)
|
|
93
|
+
for the route and plugin patterns — they're identical across all wrappers).
|
|
94
|
+
|
|
95
|
+
## What the wrapper derives
|
|
96
|
+
|
|
97
|
+
| Generic field | Derived value |
|
|
98
|
+
| ----------------------- | -------------------------------------------------------------------- |
|
|
99
|
+
| `oidc.issuer` | `https://login.microsoftonline.com/{tenantId}/v2.0` |
|
|
100
|
+
| `oidc.jwksUrl` | `https://login.microsoftonline.com/{tenantId}/discovery/v2.0/keys` |
|
|
101
|
+
| `browserLogin.url` | `https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize` |
|
|
102
|
+
| `browserLogin.tokenUrl` | `https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token` |
|
|
103
|
+
|
|
104
|
+
## Test the configuration
|
|
105
|
+
|
|
106
|
+
The fastest sanity check is to connect an MCP client:
|
|
107
|
+
|
|
108
|
+
1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
|
|
109
|
+
2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
|
|
110
|
+
3. The client should redirect you to the Microsoft sign-in page. After login,
|
|
111
|
+
the gateway's consent screen renders. Approve it.
|
|
112
|
+
4. The client receives an access token and can call `tools/list`.
|
|
113
|
+
|
|
114
|
+
If something fails partway through, walk the flow manually using the
|
|
115
|
+
[manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
|
|
116
|
+
endpoint with `curl` so you can see the raw responses.
|
|
117
|
+
|
|
118
|
+
## Common issues
|
|
119
|
+
|
|
120
|
+
- **`tenantId` rejected at boot.** The wrapper accepts only a tenant UUID, not a
|
|
121
|
+
verified domain, `common`, `organizations`, or `consumers`. Look up the tenant
|
|
122
|
+
ID under **Overview** in the Entra admin center.
|
|
123
|
+
- **`AADSTS50011` redirect URI mismatch.** The redirect URI on the app
|
|
124
|
+
registration doesn't match `https://<gateway-host>/oauth/callback` exactly.
|
|
125
|
+
Match scheme, host, and path.
|
|
126
|
+
- **`AADSTS700016` application not found.** The client ID doesn't belong to the
|
|
127
|
+
tenant the wrapper is configured with. Make sure `tenantId` and `clientId`
|
|
128
|
+
come from the same app registration.
|
|
129
|
+
|
|
130
|
+
## Related
|
|
131
|
+
|
|
132
|
+
- [Authentication overview](./overview.mdx)
|
|
133
|
+
- [Configuring a generic OIDC provider](./configuring-generic-oidc.mdx)
|
|
134
|
+
- [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
|