# Configuring OneLogin

The MCP Gateway can use OneLogin as the identity provider behind its downstream
OAuth flow. The `mcp-onelogin-oauth-inbound` policy is a OneLogin-friendly
wrapper around the generic `mcp-oauth-inbound` policy: provide your OneLogin
account subdomain, a client ID, and a client secret, and the policy derives the
OIDC v2 issuer, JWKS URL, and authorize and token URLs for you.

This guide walks through the OneLogin admin portal setup, then wires the policy
into a gateway project. Read the [authentication overview](./overview.mdx) first
for the two-layer OAuth model.

## Set up OneLogin

The MCP Gateway acts as an OAuth 2.1 authorization server in front of OneLogin.
OneLogin handles browser login; the gateway issues its own access tokens that
bind to MCP routes.

### Create an OIDC application

1. In the OneLogin admin portal, open **Applications → Applications** and click
   **Add App**.
2. Search for **OpenID Connect (OIDC)** and pick the matching app.
3. Give the application a display name (for example, `Zuplo MCP Gateway`) and
   click **Save**.
4. Open the application's **Configuration** tab.
5. Set **Redirect URIs** to `https://<gateway-host>/oauth/callback`. Add
   `http://localhost:9000/oauth/callback` for local development.
6. Set **Login Url** to your gateway origin (`https://<gateway-host>`).
7. Save.

### Configure SSO settings

1. Open the application's **SSO** tab.
2. Set **Token Endpoint Authentication Method** to **POST**.
3. Note the **Client ID** and **Client Secret** shown on the page.

### Assign users

Under the application's **Access** tab, assign the roles or users that should be
able to authenticate through the gateway.

### Find your OneLogin subdomain

Your OneLogin subdomain is the prefix of your admin portal URL. If the portal is
at `https://acme.onelogin.com`, the subdomain is `acme`. The wrapper takes only
the subdomain — no `https://`, no `.onelogin.com`, no path.

## Wire the policy into the gateway

Add the policy to `config/policies.json`:

```json
{
  "name": "onelogin-managed-oauth",
  "policyType": "mcp-onelogin-oauth-inbound",
  "handler": {
    "module": "$import(@zuplo/runtime/mcp-gateway)",
    "export": "McpOneLoginOAuthInboundPolicy",
    "options": {
      "oneLoginSubdomain": "$env(ONELOGIN_SUBDOMAIN)",
      "clientId": "$env(ONELOGIN_CLIENT_ID)",
      "clientSecret": "$env(ONELOGIN_CLIENT_SECRET)"
    }
  }
}
```

Attach the policy to each MCP route in `config/routes.oas.json` and register the
gateway plugin in `modules/zuplo.runtime.ts` (see
[Configuring Auth0](./configuring-auth0.mdx#wire-the-policy-into-the-gateway)
for the route and plugin patterns — they're identical across all wrappers).

## What the wrapper derives

Given `oneLoginSubdomain: "acme"`:

| Generic field           | Derived value                            |
| ----------------------- | ---------------------------------------- |
| `oidc.issuer`           | `https://acme.onelogin.com/oidc/2`       |
| `oidc.jwksUrl`          | `https://acme.onelogin.com/oidc/2/certs` |
| `browserLogin.url`      | `https://acme.onelogin.com/oidc/2/auth`  |
| `browserLogin.tokenUrl` | `https://acme.onelogin.com/oidc/2/token` |

These endpoint shapes follow OneLogin's OIDC provider configuration document at
`https://{oneLoginSubdomain}.onelogin.com/oidc/2/.well-known/openid-configuration`.

## Test the configuration

The fastest sanity check is to connect an MCP client:

1. Open Claude Desktop, Cursor, Claude Code, or another OAuth-aware MCP client.
2. Add a remote MCP server pointing at one of your `/mcp/{slug}` routes.
3. The client should redirect you to the OneLogin sign-in page. After login, the
   gateway's consent screen renders. Approve it.
4. The client receives an access token and can call `tools/list`.

If something fails partway through, walk the flow manually using the
[manual OAuth testing guide](./manual-oauth-testing.mdx) — it exercises every
endpoint with `curl` so you can see the raw responses.

## Common issues

- **`oneLoginSubdomain` rejected at boot.** The value includes `https://`,
  `.onelogin.com`, or a trailing path. Pass only the subdomain (`acme`).
- **`invalid_request: redirect_uri`.** The redirect URI on the OIDC application
  doesn't match `https://<gateway-host>/oauth/callback`.
- **`invalid_client` from the token endpoint.** **Token Endpoint Authentication
  Method** isn't set to **POST** on the application's SSO tab.

## Related

- [Authentication overview](./overview.mdx)
- [Configuring a generic OIDC provider](./configuring-generic-oidc.mdx)
- [Per-user OAuth to upstream MCP servers](./upstream-oauth.mdx)
