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,242 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Configuring a generic OIDC provider"
|
|
3
|
+
sidebar_label: "Generic OIDC"
|
|
4
|
+
description:
|
|
5
|
+
Configure any OIDC-compatible identity provider — Ory Hydra, Authentik,
|
|
6
|
+
ZITADEL, FusionAuth, PingFederate, or a custom OIDC server — to back the MCP
|
|
7
|
+
Gateway's downstream OAuth using the mcp-oauth-inbound policy.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
The `mcp-oauth-inbound` policy is the catch-all for OIDC identity providers that
|
|
11
|
+
don't yet have a first-class wrapper. It accepts the OIDC URLs explicitly and
|
|
12
|
+
otherwise behaves the same as every per-provider wrapper.
|
|
13
|
+
|
|
14
|
+
Use this policy when your IdP doesn't appear in the
|
|
15
|
+
[provider catalog](./overview.mdx#identity-providers). Common cases:
|
|
16
|
+
|
|
17
|
+
- **Ory Hydra** — self-hosted OAuth 2.0/OIDC.
|
|
18
|
+
- **Authentik** — open-source IdP.
|
|
19
|
+
- **ZITADEL** — open-source IdP.
|
|
20
|
+
- **FusionAuth** — self-hosted IdP.
|
|
21
|
+
- **PingFederate** — enterprise IdP (use this policy, not
|
|
22
|
+
`mcp-ping-oauth-inbound`, which is for PingOne cloud).
|
|
23
|
+
- **A custom OIDC server** you operate yourself.
|
|
24
|
+
|
|
25
|
+
If your IdP is on the [catalog](./overview.mdx#identity-providers), use the
|
|
26
|
+
dedicated wrapper instead — it validates provider-specific inputs at boot.
|
|
27
|
+
|
|
28
|
+
Read the [authentication overview](./overview.mdx) first for the two-layer
|
|
29
|
+
model.
|
|
30
|
+
|
|
31
|
+
## What the gateway needs from your IdP
|
|
32
|
+
|
|
33
|
+
The gateway needs three pieces of information about your IdP:
|
|
34
|
+
|
|
35
|
+
1. The **OIDC issuer URL** — the value of `iss` in ID tokens.
|
|
36
|
+
2. The **JWKS URL** — where the gateway fetches the IdP's public keys to verify
|
|
37
|
+
ID tokens.
|
|
38
|
+
3. The **authorize URL** — where the gateway redirects the user's browser to log
|
|
39
|
+
in.
|
|
40
|
+
|
|
41
|
+
For the federated authorization-code exchange you also need a token URL, a
|
|
42
|
+
client ID, and a client secret. The [options reference](#full-options-reference)
|
|
43
|
+
below lists every field.
|
|
44
|
+
|
|
45
|
+
Most OIDC providers publish all four URLs in a discovery document at
|
|
46
|
+
`{issuer}/.well-known/openid-configuration`. Fetch that document in a browser to
|
|
47
|
+
copy the values.
|
|
48
|
+
|
|
49
|
+
## Set up the OIDC application
|
|
50
|
+
|
|
51
|
+
Each IdP exposes its application registration differently, but every flow lands
|
|
52
|
+
at the same place:
|
|
53
|
+
|
|
54
|
+
1. Create a new OIDC web application (or "regular web application", "OIDC
|
|
55
|
+
client", "confidential client" — terminology varies).
|
|
56
|
+
2. Set the **redirect URI** to `https://<gateway-host>/oauth/callback`. Add
|
|
57
|
+
`http://localhost:9000/oauth/callback` for local development with
|
|
58
|
+
`zuplo dev`.
|
|
59
|
+
3. Note the **client ID** and **client secret**.
|
|
60
|
+
4. Restrict the application to the users or groups who should be able to
|
|
61
|
+
authenticate against the gateway.
|
|
62
|
+
|
|
63
|
+
## Wire the policy into the gateway
|
|
64
|
+
|
|
65
|
+
Add the policy to `config/policies.json`:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"name": "oidc-managed-oauth",
|
|
70
|
+
"policyType": "mcp-oauth-inbound",
|
|
71
|
+
"handler": {
|
|
72
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
73
|
+
"export": "McpOAuthInboundPolicy",
|
|
74
|
+
"options": {
|
|
75
|
+
"oidc": {
|
|
76
|
+
"issuer": "https://idp.example.com",
|
|
77
|
+
"jwksUrl": "https://idp.example.com/.well-known/jwks.json"
|
|
78
|
+
},
|
|
79
|
+
"browserLogin": {
|
|
80
|
+
"url": "https://idp.example.com/oauth2/authorize",
|
|
81
|
+
"tokenUrl": "https://idp.example.com/oauth2/token",
|
|
82
|
+
"clientId": "$env(OIDC_CLIENT_ID)",
|
|
83
|
+
"clientSecret": "$env(OIDC_CLIENT_SECRET)"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Set `OIDC_CLIENT_ID` and `OIDC_CLIENT_SECRET` in your project's environment
|
|
91
|
+
configuration (the secret goes in the secret store).
|
|
92
|
+
|
|
93
|
+
Attach the policy to each MCP route in `config/routes.oas.json`:
|
|
94
|
+
|
|
95
|
+
```jsonc
|
|
96
|
+
{
|
|
97
|
+
"paths": {
|
|
98
|
+
"/mcp/linear-v1": {
|
|
99
|
+
"get,post": {
|
|
100
|
+
"operationId": "linear-mcp-server",
|
|
101
|
+
"x-zuplo-route": {
|
|
102
|
+
"corsPolicy": "none",
|
|
103
|
+
"handler": {
|
|
104
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
105
|
+
"export": "McpProxyHandler",
|
|
106
|
+
"options": {
|
|
107
|
+
"rewritePattern": "https://mcp.linear.app/mcp",
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
"policies": {
|
|
111
|
+
"inbound": ["oidc-managed-oauth", "mcp-token-exchange-linear"],
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Register the gateway plugin in `modules/zuplo.runtime.ts`:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
import { RuntimeExtensions } from "@zuplo/runtime";
|
|
124
|
+
import { McpGatewayPlugin } from "@zuplo/runtime/mcp-gateway";
|
|
125
|
+
|
|
126
|
+
export function runtimeInit(runtime: RuntimeExtensions) {
|
|
127
|
+
runtime.addPlugin(new McpGatewayPlugin());
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
One MCP OAuth policy serves every MCP route in the project. The gateway rejects
|
|
132
|
+
projects that declare more than one MCP OAuth policy.
|
|
133
|
+
|
|
134
|
+
## Local development shortcut
|
|
135
|
+
|
|
136
|
+
For local development without round-tripping a real IdP, set `browserLogin.url`
|
|
137
|
+
to the loopback dev-login endpoint:
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"options": {
|
|
142
|
+
"oidc": {
|
|
143
|
+
"issuer": "http://localhost:9000/",
|
|
144
|
+
"jwksUrl": "http://localhost:9000/dev/jwks"
|
|
145
|
+
},
|
|
146
|
+
"browserLogin": {
|
|
147
|
+
"url": "http://127.0.0.1:9000/oauth/dev-login"
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
When `browserLogin.url` points at `/oauth/dev-login`, you don't need `tokenUrl`,
|
|
154
|
+
`clientId`, or `clientSecret`. The endpoint is only served on loopback origins;
|
|
155
|
+
production deployments cannot reach it.
|
|
156
|
+
|
|
157
|
+
See the [local development guide](../code-config/local-development.mdx) for the
|
|
158
|
+
rest of the local setup.
|
|
159
|
+
|
|
160
|
+
## Full options reference
|
|
161
|
+
|
|
162
|
+
`mcp-oauth-inbound` has two required option groups: `oidc` and `browserLogin`.
|
|
163
|
+
|
|
164
|
+
| Option | Required | Default | Notes |
|
|
165
|
+
| -------------------------------- | ------------------ | ---------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
166
|
+
| `oidc.issuer` | yes | — | The OIDC issuer URL. Must include the scheme. |
|
|
167
|
+
| `oidc.jwksUrl` | yes | — | JWKS endpoint that publishes the IdP's signing keys. |
|
|
168
|
+
| `oidc.audience` | no | unset | Optional ID-token audience override. Leave unset when ID tokens use the OIDC `client_id` as their audience. |
|
|
169
|
+
| `browserLogin.url` | yes | — | The IdP's `/authorize` endpoint. The loopback `/oauth/dev-login` shortcut works for local dev. |
|
|
170
|
+
| `browserLogin.tokenUrl` | for federated OIDC | — | The IdP's token endpoint. Required for the federated authorization-code exchange. |
|
|
171
|
+
| `browserLogin.clientId` | for federated OIDC | — | OIDC client_id registered with the IdP. |
|
|
172
|
+
| `browserLogin.clientSecret` | for federated OIDC | — | OIDC client_secret. Use `$env(...)`. |
|
|
173
|
+
| `browserLogin.scope` | no | `openid profile email` | OIDC scopes requested during browser login. |
|
|
174
|
+
| `browserLogin.audience` | no | unset | Optional `audience` parameter for Auth0-style API audiences. |
|
|
175
|
+
| `browserLogin.remoteTimeoutMs` | no | `10000` | Outbound timeout for IdP calls. |
|
|
176
|
+
| `browserLogin.stateTtlSeconds` | no | `900` | Browser-login state record lifetime. |
|
|
177
|
+
| `browserLogin.sessionTtlSeconds` | no | `28800` | Browser session cookie lifetime (8 hours). |
|
|
178
|
+
| `gateway.accessTokenTtlSeconds` | no | `900` | Gateway-issued access token lifetime. |
|
|
179
|
+
| `gateway.refreshTokenTtlSeconds` | no | long-lived | Gateway-issued refresh token lifetime. |
|
|
180
|
+
| `gateway.cimdEnabled` | no | `true` | Advertise CIMD support in AS metadata. |
|
|
181
|
+
|
|
182
|
+
## Notes for specific providers
|
|
183
|
+
|
|
184
|
+
- **Ory Hydra.** Discovery lives at `{issuer}/.well-known/openid-configuration`;
|
|
185
|
+
set the issuer to the public-facing Hydra URL.
|
|
186
|
+
- **Authentik.** The issuer is `https://<authentik-host>/application/o/<slug>/`
|
|
187
|
+
(note the trailing slash). The metadata document is at that issuer plus
|
|
188
|
+
`.well-known/openid-configuration`.
|
|
189
|
+
- **ZITADEL.** The issuer is your ZITADEL custom domain; metadata is at
|
|
190
|
+
`{issuer}/.well-known/openid-configuration`.
|
|
191
|
+
- **FusionAuth.** The issuer is your FusionAuth host; metadata is at
|
|
192
|
+
`{issuer}/.well-known/openid-configuration`.
|
|
193
|
+
- **PingFederate.** Use this generic policy (not the PingOne wrapper).
|
|
194
|
+
PingFederate deployments can customize issuer hosts, issuer paths, and
|
|
195
|
+
endpoint paths; copy the four URLs from your federation metadata.
|
|
196
|
+
- **Google Workspace.** Google has a first-class wrapper —
|
|
197
|
+
[Configuring Google](./configuring-google.mdx).
|
|
198
|
+
- **Microsoft Entra ID.** Entra has a first-class wrapper —
|
|
199
|
+
[Configuring Microsoft Entra](./configuring-entra.mdx).
|
|
200
|
+
- **Keycloak.** Keycloak has a first-class wrapper —
|
|
201
|
+
[Configuring Keycloak](./configuring-keycloak.mdx).
|
|
202
|
+
|
|
203
|
+
In every case, the gateway only needs the four URL fields (issuer, JWKS,
|
|
204
|
+
authorize, token) plus a client ID and secret.
|
|
205
|
+
|
|
206
|
+
## Test the configuration
|
|
207
|
+
|
|
208
|
+
The fastest sanity check is to connect an MCP client:
|
|
209
|
+
|
|
210
|
+
1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
|
|
211
|
+
2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
|
|
212
|
+
3. The client should redirect you to your IdP's login page. After login, the
|
|
213
|
+
gateway's consent screen renders. Approve it.
|
|
214
|
+
4. The client receives an access token and can call `tools/list`.
|
|
215
|
+
|
|
216
|
+
If something fails partway through, walk the flow manually using the
|
|
217
|
+
[manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
|
|
218
|
+
endpoint with `curl` so you can see the raw responses.
|
|
219
|
+
|
|
220
|
+
## Common issues
|
|
221
|
+
|
|
222
|
+
- **The gateway returns 500 at boot.** A required option is missing or invalid.
|
|
223
|
+
Check the runtime logs for the configuration error.
|
|
224
|
+
- **ID token verification fails.** The `oidc.jwksUrl` doesn't match the IdP's
|
|
225
|
+
actual JWKS endpoint, or the IdP rotated keys. Restart the gateway to clear
|
|
226
|
+
the JWKS cache.
|
|
227
|
+
- **`invalid_audience` from the gateway's token endpoint.** The MCP client is
|
|
228
|
+
reusing a token bound to a different route. Each gateway-issued token is
|
|
229
|
+
scoped to one MCP route.
|
|
230
|
+
- **MCP client can't discover the AS.** Confirm the `mcp-oauth-inbound` policy
|
|
231
|
+
is attached to the route in `routes.oas.json` and the `McpGatewayPlugin` is
|
|
232
|
+
registered in `modules/zuplo.runtime.ts`.
|
|
233
|
+
- **Browser login redirects but the callback fails.** The
|
|
234
|
+
`https://<gateway-host>/oauth/callback` URL isn't on the application's
|
|
235
|
+
redirect URI allow-list at the IdP.
|
|
236
|
+
|
|
237
|
+
## Related
|
|
238
|
+
|
|
239
|
+
- [Authentication overview](./overview.mdx) — the provider catalog and the
|
|
240
|
+
two-layer OAuth model.
|
|
241
|
+
- [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
|
|
242
|
+
- [Manual OAuth testing](./manual-oauth-testing.mdx)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Configuring Google"
|
|
3
|
+
sidebar_label: "Google"
|
|
4
|
+
description:
|
|
5
|
+
Configure Google as the identity provider behind the MCP Gateway's downstream
|
|
6
|
+
OAuth using the mcp-google-oauth-inbound policy. Covers OAuth client setup in
|
|
7
|
+
Google Cloud and wiring the policy in your gateway project.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
The MCP Gateway can use Google as the identity provider behind its downstream
|
|
11
|
+
OAuth flow. The `mcp-google-oauth-inbound` policy is a Google-friendly wrapper
|
|
12
|
+
around the generic `mcp-oauth-inbound` policy: provide a Google OAuth client ID
|
|
13
|
+
and client secret, and the policy uses Google's fixed OIDC issuer
|
|
14
|
+
(`https://accounts.google.com`) and discovery document automatically.
|
|
15
|
+
|
|
16
|
+
This guide walks through the Google Cloud Console setup, then wires the policy
|
|
17
|
+
into a gateway project. Read the [authentication overview](./overview.mdx) first
|
|
18
|
+
for the two-layer OAuth model.
|
|
19
|
+
|
|
20
|
+
## Set up Google
|
|
21
|
+
|
|
22
|
+
The MCP Gateway acts as an OAuth 2.1 authorization server in front of Google.
|
|
23
|
+
Google handles browser login; the gateway issues its own access tokens that bind
|
|
24
|
+
to MCP routes.
|
|
25
|
+
|
|
26
|
+
### Create an OAuth client
|
|
27
|
+
|
|
28
|
+
1. In the Google Cloud Console, switch to the project that should own the OAuth
|
|
29
|
+
client, then open **APIs & Services → Credentials**.
|
|
30
|
+
2. Click **Create credentials → OAuth client ID**. (If prompted, configure the
|
|
31
|
+
**OAuth consent screen** first — pick **Internal** for Google Workspace
|
|
32
|
+
tenants or **External** for general use, then add the user types you want to
|
|
33
|
+
allow.)
|
|
34
|
+
3. Choose **Web application** as the application type.
|
|
35
|
+
4. Give the client a name (for example, `Zuplo MCP Gateway`).
|
|
36
|
+
5. Under **Authorized redirect URIs**, add
|
|
37
|
+
`https://<gateway-host>/oauth/callback`. Add
|
|
38
|
+
`http://localhost:9000/oauth/callback` for local development with
|
|
39
|
+
`zuplo dev`.
|
|
40
|
+
6. Click **Create**.
|
|
41
|
+
|
|
42
|
+
Note the **Client ID** (looks like
|
|
43
|
+
`123456789012-abc123def456.apps.googleusercontent.com`) and the **Client
|
|
44
|
+
secret** from the dialog. The wrapper rejects values that aren't in Google's
|
|
45
|
+
OAuth client ID shape.
|
|
46
|
+
|
|
47
|
+
## Wire the policy into the gateway
|
|
48
|
+
|
|
49
|
+
Add the policy to `config/policies.json`:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"name": "google-managed-oauth",
|
|
54
|
+
"policyType": "mcp-google-oauth-inbound",
|
|
55
|
+
"handler": {
|
|
56
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
57
|
+
"export": "McpGoogleOAuthInboundPolicy",
|
|
58
|
+
"options": {
|
|
59
|
+
"clientId": "$env(GOOGLE_CLIENT_ID)",
|
|
60
|
+
"clientSecret": "$env(GOOGLE_CLIENT_SECRET)"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Set the two environment variables in your project's environment configuration.
|
|
67
|
+
The secret values belong in the project secret store.
|
|
68
|
+
|
|
69
|
+
Attach the policy to each MCP route in `config/routes.oas.json` and register the
|
|
70
|
+
gateway plugin in `modules/zuplo.runtime.ts` (see
|
|
71
|
+
[Configuring Auth0](./configuring-auth0.mdx#wire-the-policy-into-the-gateway)
|
|
72
|
+
for the route and plugin patterns — they're identical across all wrappers).
|
|
73
|
+
|
|
74
|
+
## What the wrapper derives
|
|
75
|
+
|
|
76
|
+
Google publishes a fixed OIDC discovery document at
|
|
77
|
+
`https://accounts.google.com/.well-known/openid-configuration`. The wrapper
|
|
78
|
+
hard-codes the corresponding endpoints:
|
|
79
|
+
|
|
80
|
+
| Generic field | Derived value |
|
|
81
|
+
| ----------------------- | ---------------------------------------------- |
|
|
82
|
+
| `oidc.issuer` | `https://accounts.google.com` |
|
|
83
|
+
| `oidc.jwksUrl` | `https://www.googleapis.com/oauth2/v3/certs` |
|
|
84
|
+
| `browserLogin.url` | `https://accounts.google.com/o/oauth2/v2/auth` |
|
|
85
|
+
| `browserLogin.tokenUrl` | `https://oauth2.googleapis.com/token` |
|
|
86
|
+
|
|
87
|
+
## Test the configuration
|
|
88
|
+
|
|
89
|
+
The fastest sanity check is to connect an MCP client:
|
|
90
|
+
|
|
91
|
+
1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
|
|
92
|
+
2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
|
|
93
|
+
3. The client should redirect you to the Google sign-in page. After login, the
|
|
94
|
+
gateway's consent screen renders. Approve it.
|
|
95
|
+
4. The client receives an access token and can call `tools/list`.
|
|
96
|
+
|
|
97
|
+
If something fails partway through, walk the flow manually using the
|
|
98
|
+
[manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
|
|
99
|
+
endpoint with `curl` so you can see the raw responses.
|
|
100
|
+
|
|
101
|
+
## Common issues
|
|
102
|
+
|
|
103
|
+
- **`clientId` rejected at boot.** The wrapper rejects values that don't use
|
|
104
|
+
Google's OAuth client ID shape — issuer URLs, API hostnames, project numbers.
|
|
105
|
+
Use the full `123456789012-abc123def456.apps.googleusercontent.com` form.
|
|
106
|
+
- **`redirect_uri_mismatch` from Google.** The redirect URI on the OAuth client
|
|
107
|
+
doesn't match `https://<gateway-host>/oauth/callback` exactly. Match scheme,
|
|
108
|
+
host, and path.
|
|
109
|
+
- **`access_denied` for Google Workspace users.** The OAuth consent screen is
|
|
110
|
+
set to **Internal** but the user belongs to a different workspace, or the user
|
|
111
|
+
isn't on the **Test users** list during pre-verification.
|
|
112
|
+
|
|
113
|
+
## Related
|
|
114
|
+
|
|
115
|
+
- [Authentication overview](./overview.mdx)
|
|
116
|
+
- [Configuring a generic OIDC provider](./configuring-generic-oidc.mdx)
|
|
117
|
+
- [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Configuring Keycloak"
|
|
3
|
+
sidebar_label: "Keycloak"
|
|
4
|
+
description:
|
|
5
|
+
Configure Keycloak to back the MCP Gateway's downstream OAuth using the
|
|
6
|
+
mcp-keycloak-oauth-inbound policy. Covers realm client setup and wiring the
|
|
7
|
+
policy in your gateway project.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
The MCP Gateway can use Keycloak as the identity provider behind its downstream
|
|
11
|
+
OAuth flow. The `mcp-keycloak-oauth-inbound` policy is a Keycloak-friendly
|
|
12
|
+
wrapper around the generic `mcp-oauth-inbound` policy: provide your Keycloak
|
|
13
|
+
base URL, a realm name, a client ID, and a client secret, and the policy derives
|
|
14
|
+
the realm-issuer URL, JWKS URL, and authorize and token URLs from Keycloak's
|
|
15
|
+
standard OpenID Connect endpoint layout.
|
|
16
|
+
|
|
17
|
+
This guide walks through the Keycloak admin console setup, then wires the policy
|
|
18
|
+
into a gateway project. Read the [authentication overview](./overview.mdx) first
|
|
19
|
+
for the two-layer OAuth model.
|
|
20
|
+
|
|
21
|
+
## Set up Keycloak
|
|
22
|
+
|
|
23
|
+
The MCP Gateway acts as an OAuth 2.1 authorization server in front of Keycloak.
|
|
24
|
+
Keycloak handles browser login; the gateway issues its own access tokens that
|
|
25
|
+
bind to MCP routes.
|
|
26
|
+
|
|
27
|
+
### Create a client in the realm
|
|
28
|
+
|
|
29
|
+
1. In the Keycloak admin console, switch to the realm you want the gateway to
|
|
30
|
+
use.
|
|
31
|
+
2. Open **Clients** and click **Create client**.
|
|
32
|
+
3. Give the client a Client ID (for example, `zuplo-mcp-gateway`) and click
|
|
33
|
+
**Next**.
|
|
34
|
+
4. Enable **Client authentication** (so the client requires a secret) and leave
|
|
35
|
+
**Standard flow** (authorization code) enabled. Disable **Service accounts
|
|
36
|
+
roles** and **Direct access grants** — the gateway only needs the browser
|
|
37
|
+
code flow.
|
|
38
|
+
5. Click **Next**.
|
|
39
|
+
6. Set **Valid redirect URIs** to `https://<gateway-host>/oauth/callback`. Add
|
|
40
|
+
`http://localhost:9000/oauth/callback` for local development.
|
|
41
|
+
7. Set **Web origins** to `https://<gateway-host>` (and `http://localhost:9000`
|
|
42
|
+
for local dev).
|
|
43
|
+
8. Click **Save**.
|
|
44
|
+
|
|
45
|
+
### Note the client credentials
|
|
46
|
+
|
|
47
|
+
Open the client's **Credentials** tab. Copy the **Client secret**. The **Client
|
|
48
|
+
ID** is the value you set above.
|
|
49
|
+
|
|
50
|
+
## Wire the policy into the gateway
|
|
51
|
+
|
|
52
|
+
Add the policy to `config/policies.json`:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"name": "keycloak-managed-oauth",
|
|
57
|
+
"policyType": "mcp-keycloak-oauth-inbound",
|
|
58
|
+
"handler": {
|
|
59
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
60
|
+
"export": "McpKeycloakOAuthInboundPolicy",
|
|
61
|
+
"options": {
|
|
62
|
+
"keycloakBaseUrl": "$env(KEYCLOAK_BASE_URL)",
|
|
63
|
+
"realm": "$env(KEYCLOAK_REALM)",
|
|
64
|
+
"clientId": "$env(KEYCLOAK_CLIENT_ID)",
|
|
65
|
+
"clientSecret": "$env(KEYCLOAK_CLIENT_SECRET)"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
:::caution
|
|
72
|
+
|
|
73
|
+
`keycloakBaseUrl` is the Keycloak server root, without `/realms/{realm}` — set
|
|
74
|
+
the realm separately on the `realm` option. If your deployment uses a path
|
|
75
|
+
prefix (legacy `/auth`), include that in `keycloakBaseUrl`
|
|
76
|
+
(`https://sso.example.com/auth`).
|
|
77
|
+
|
|
78
|
+
:::
|
|
79
|
+
|
|
80
|
+
Attach the policy to each MCP route in `config/routes.oas.json` and register the
|
|
81
|
+
gateway plugin in `modules/zuplo.runtime.ts` (see
|
|
82
|
+
[Configuring Auth0](./configuring-auth0.mdx#wire-the-policy-into-the-gateway)
|
|
83
|
+
for the route and plugin patterns — they're identical across all wrappers).
|
|
84
|
+
|
|
85
|
+
## What the wrapper derives
|
|
86
|
+
|
|
87
|
+
Given `keycloakBaseUrl: "https://sso.example.com"` and
|
|
88
|
+
`realm: "customer-portal"`:
|
|
89
|
+
|
|
90
|
+
| Generic field | Derived value |
|
|
91
|
+
| ----------------------- | ------------------------------------------------------------------------------ |
|
|
92
|
+
| `oidc.issuer` | `https://sso.example.com/realms/customer-portal` |
|
|
93
|
+
| `oidc.jwksUrl` | `https://sso.example.com/realms/customer-portal/protocol/openid-connect/certs` |
|
|
94
|
+
| `browserLogin.url` | `https://sso.example.com/realms/customer-portal/protocol/openid-connect/auth` |
|
|
95
|
+
| `browserLogin.tokenUrl` | `https://sso.example.com/realms/customer-portal/protocol/openid-connect/token` |
|
|
96
|
+
|
|
97
|
+
## Test the configuration
|
|
98
|
+
|
|
99
|
+
The fastest sanity check is to connect an MCP client:
|
|
100
|
+
|
|
101
|
+
1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
|
|
102
|
+
2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
|
|
103
|
+
3. The client should redirect you to the Keycloak sign-in page. After login, the
|
|
104
|
+
gateway's consent screen renders. Approve it.
|
|
105
|
+
4. The client receives an access token and can call `tools/list`.
|
|
106
|
+
|
|
107
|
+
If something fails partway through, walk the flow manually using the
|
|
108
|
+
[manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
|
|
109
|
+
endpoint with `curl` so you can see the raw responses.
|
|
110
|
+
|
|
111
|
+
## Common issues
|
|
112
|
+
|
|
113
|
+
- **`keycloakBaseUrl` rejected at boot.** The value includes `/realms/...`.
|
|
114
|
+
Strip the realm path; pass the realm name on the `realm` option instead.
|
|
115
|
+
- **`Invalid redirect_uri` from Keycloak.** The callback URL on the client
|
|
116
|
+
doesn't match `https://<gateway-host>/oauth/callback`.
|
|
117
|
+
- **`Invalid client credentials`.** The client isn't a confidential client
|
|
118
|
+
(Client authentication off), or the secret value doesn't match. Re-copy the
|
|
119
|
+
secret from the **Credentials** tab.
|
|
120
|
+
|
|
121
|
+
## Related
|
|
122
|
+
|
|
123
|
+
- [Authentication overview](./overview.mdx)
|
|
124
|
+
- [Configuring a generic OIDC provider](./configuring-generic-oidc.mdx)
|
|
125
|
+
- [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Configuring Logto"
|
|
3
|
+
sidebar_label: "Logto"
|
|
4
|
+
description:
|
|
5
|
+
Configure Logto to back the MCP Gateway's downstream OAuth using the
|
|
6
|
+
mcp-logto-oauth-inbound policy. Covers application setup and wiring the policy
|
|
7
|
+
in your gateway project.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
The MCP Gateway can use [Logto](https://logto.io/) as the identity provider
|
|
11
|
+
behind its downstream OAuth flow. The `mcp-logto-oauth-inbound` policy is a
|
|
12
|
+
Logto-friendly wrapper around the generic `mcp-oauth-inbound` policy: provide
|
|
13
|
+
your Logto tenant endpoint, a client ID, and a client secret, and the policy
|
|
14
|
+
derives the OIDC issuer, JWKS URL, and authorize and token URLs from Logto's
|
|
15
|
+
`/oidc` mount point.
|
|
16
|
+
|
|
17
|
+
This guide walks through the Logto console setup, then wires the policy into a
|
|
18
|
+
gateway project. Read the [authentication overview](./overview.mdx) first for
|
|
19
|
+
the two-layer OAuth model.
|
|
20
|
+
|
|
21
|
+
## Set up Logto
|
|
22
|
+
|
|
23
|
+
The MCP Gateway acts as an OAuth 2.1 authorization server in front of Logto.
|
|
24
|
+
Logto handles browser login; the gateway issues its own access tokens that bind
|
|
25
|
+
to MCP routes.
|
|
26
|
+
|
|
27
|
+
### Create a Traditional Web application
|
|
28
|
+
|
|
29
|
+
1. In the Logto Console, open **Applications** and click **Create application**.
|
|
30
|
+
2. Pick **Traditional Web** as the application type. (Not SPA, not Native — the
|
|
31
|
+
gateway needs a confidential client with a secret.)
|
|
32
|
+
3. Give the application a name (for example, `Zuplo MCP Gateway`) and click
|
|
33
|
+
**Create application**.
|
|
34
|
+
4. On the application's **Settings** tab, set **Redirect URIs** to
|
|
35
|
+
`https://<gateway-host>/oauth/callback`. Add
|
|
36
|
+
`http://localhost:9000/oauth/callback` for local development.
|
|
37
|
+
5. Save.
|
|
38
|
+
|
|
39
|
+
Note the **App ID** (= client ID) and **App secret** (= client secret) from the
|
|
40
|
+
application's detail page.
|
|
41
|
+
|
|
42
|
+
### Find your tenant endpoint
|
|
43
|
+
|
|
44
|
+
Open **Settings → Domains** in the Logto Console. Your default tenant endpoint
|
|
45
|
+
looks like `https://your-tenant.logto.app`. If you've configured a custom
|
|
46
|
+
domain, use that instead. The wrapper takes the origin only — no `/oidc`, no
|
|
47
|
+
`.well-known/...`, no trailing slash.
|
|
48
|
+
|
|
49
|
+
## Wire the policy into the gateway
|
|
50
|
+
|
|
51
|
+
Add the policy to `config/policies.json`:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"name": "logto-managed-oauth",
|
|
56
|
+
"policyType": "mcp-logto-oauth-inbound",
|
|
57
|
+
"handler": {
|
|
58
|
+
"module": "$import(@zuplo/runtime/mcp-gateway)",
|
|
59
|
+
"export": "McpLogtoOAuthInboundPolicy",
|
|
60
|
+
"options": {
|
|
61
|
+
"logtoEndpoint": "$env(LOGTO_ENDPOINT)",
|
|
62
|
+
"clientId": "$env(LOGTO_CLIENT_ID)",
|
|
63
|
+
"clientSecret": "$env(LOGTO_CLIENT_SECRET)"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Attach the policy to each MCP route in `config/routes.oas.json` and register the
|
|
70
|
+
gateway plugin in `modules/zuplo.runtime.ts` (see
|
|
71
|
+
[Configuring Auth0](./configuring-auth0.mdx#wire-the-policy-into-the-gateway)
|
|
72
|
+
for the route and plugin patterns — they're identical across all wrappers).
|
|
73
|
+
|
|
74
|
+
## What the wrapper derives
|
|
75
|
+
|
|
76
|
+
Given `logtoEndpoint: "https://acme.logto.app"`:
|
|
77
|
+
|
|
78
|
+
| Generic field | Derived value |
|
|
79
|
+
| ----------------------- | ----------------------------------- |
|
|
80
|
+
| `oidc.issuer` | `https://acme.logto.app/oidc` |
|
|
81
|
+
| `oidc.jwksUrl` | `https://acme.logto.app/oidc/jwks` |
|
|
82
|
+
| `browserLogin.url` | `https://acme.logto.app/oidc/auth` |
|
|
83
|
+
| `browserLogin.tokenUrl` | `https://acme.logto.app/oidc/token` |
|
|
84
|
+
|
|
85
|
+
These endpoint shapes come from Logto's OIDC provider mounted at `/oidc` and its
|
|
86
|
+
discovery document at
|
|
87
|
+
`https://<your-logto-endpoint>/oidc/.well-known/openid-configuration`.
|
|
88
|
+
|
|
89
|
+
## Test the configuration
|
|
90
|
+
|
|
91
|
+
The fastest sanity check is to connect an MCP client:
|
|
92
|
+
|
|
93
|
+
1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
|
|
94
|
+
2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
|
|
95
|
+
3. The client should redirect you to the Logto sign-in page. After login, the
|
|
96
|
+
gateway's consent screen renders. Approve it.
|
|
97
|
+
4. The client receives an access token and can call `tools/list`.
|
|
98
|
+
|
|
99
|
+
If something fails partway through, walk the flow manually using the
|
|
100
|
+
[manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
|
|
101
|
+
endpoint with `curl` so you can see the raw responses.
|
|
102
|
+
|
|
103
|
+
## Common issues
|
|
104
|
+
|
|
105
|
+
- **`logtoEndpoint` rejected at boot.** The value includes `/oidc`,
|
|
106
|
+
`/.well-known/openid-configuration`, or another path. Use the bare tenant
|
|
107
|
+
endpoint origin.
|
|
108
|
+
- **`redirect_uri` rejected by Logto.** The redirect URI on the application
|
|
109
|
+
doesn't match `https://<gateway-host>/oauth/callback`. Match scheme, host, and
|
|
110
|
+
path.
|
|
111
|
+
|
|
112
|
+
## Related
|
|
113
|
+
|
|
114
|
+
- [Authentication overview](./overview.mdx)
|
|
115
|
+
- [Configuring a generic OIDC provider](./configuring-generic-oidc.mdx)
|
|
116
|
+
- [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
|