# Keycloak client administration for the Ops Webapp and hosted MCP servers

The Ops Webapp and hosted MCP servers (Ops MCP, Cloud MCP) authenticate via
Keycloak clients in the `airbyte` realm. Keycloak client configuration is managed
manually through the Keycloak Admin Console — it is not owned by Pulumi or any
automated pipeline.

For the canonical Keycloak administration references, see the Notion pages:

- [Keycloak Operations Guide](https://app.notion.com/p/32c1b3df260c8116b6ffdbdcad24038f)
- [Keycloak Server Administration Guide](https://app.notion.com/p/2491b3df260c80cf914ed45245eb8300)
- [Keycloak Admin Console Access (runbook)](https://app.notion.com/p/65c5210e8ab14c78a4dc827b4ac229e9)

## Ops Webapp client

| Field | Value |
|-------|-------|
| Realm | `airbyte` |
| Client ID | `airbyte-ops-webapp-client` |
| Issuer | `https://cloud.airbyte.com/auth/realms/airbyte` |
| PKCE | `S256` |
| Client type | Confidential (client secret required for token exchange) |

### Registered redirect URIs

| URI | Purpose |
|-----|---------|
| `http://localhost:3000/oauth/callback` | Local development |
| `https://ops.internal.airbyte.ai/oauth/callback` | Production |
| `https://preview.ops.internal.airbyte.ai/oauth/callback` | Preview deploys |

> A single fixed preview subdomain is used instead of a wildcard so the same
> redirect URI can be registered in both Keycloak and Google OAuth (which does
> not support wildcard URIs).

## Ops MCP client

The hosted Ops MCP server uses FastMCP's `OIDCProxy` for Keycloak OIDC
authentication (Authorization Code + PKCE). This is a separate client from
the Ops Webapp client.

| Field | Value |
|-------|-------|
| Realm | `airbyte` |
| Client ID | `ops-mcp-client` |
| Issuer | `https://cloud.airbyte.com/auth/realms/airbyte` |
| PKCE | `S256` |
| Client type | Confidential (client secret required for token exchange) |

### Registered redirect URIs

| URI | Purpose |
|-----|---------|
| `http://localhost:8080/auth/callback` | Local development |
| `https://mcp.internal.airbyte.ai/ops-mcp/auth/callback` | Production |
| `https://mcp.internal.airbyte.ai/ops-mcp-preview/auth/callback` | Preview deploys |

### Creating the Ops MCP client

To create the `ops-mcp-client` in Keycloak:

1. Access the Keycloak Admin Console (steps below).
2. In the `airbyte` realm, go to **Clients** → **Create client**.
3. Set Client ID to `ops-mcp-client`, Client type to **OpenID Connect**.
4. Enable **Client authentication** (confidential) and **Standard flow**.
5. Set PKCE Code Challenge Method to `S256`.
6. Add the redirect URIs listed above under **Valid Redirect URIs**.
7. Click **Save** and note the client secret from the **Credentials** tab.
8. Store the client secret in GCP Secret Manager as `ops-mcp-oauth-client-secret`
   in the `internal-airbyte-ai-infra` project.

## Cloud MCP client

The hosted Cloud (Replication) MCP server uses the same `OIDCProxy` pattern
as the Ops MCP, but with its own client.

| Field | Value |
|-------|-------|
| Realm | `airbyte` |
| Client ID | `cloud-mcp-client` |
| Issuer | `https://cloud.airbyte.com/auth/realms/airbyte` |
| PKCE | `S256` |
| Client type | Confidential (client secret required for token exchange) |

### Registered redirect URIs

| URI | Purpose |
|-----|---------|
| `http://localhost:8080/auth/callback` | Local development |
| `https://mcp.internal.airbyte.ai/cloud-mcp/auth/callback` | Production |
| `https://mcp.internal.airbyte.ai/cloud-mcp-preview/auth/callback` | Preview deploys |

### Creating the Cloud MCP client

Follow the same steps as [Creating the Ops MCP client](#creating-the-ops-mcp-client),
using `cloud-mcp-client` as the Client ID and the redirect URIs listed above.
Store the client secret in GCP Secret Manager as `cloud-mcp-oauth-client-secret`
in the `internal-airbyte-ai-infra` project.

## Accessing the Keycloak Admin Console

Keycloak is not exposed through the Cloud Load Balancer. Access requires a
`kubectl port-forward` through the production Kubernetes cluster (which in turn
requires a Tailscale VPN connection to reach the cluster's internal IP).

### Prerequisites

#### CLI tools

Install the required CLI tools (if not already present):

```bash
brew install kubectl kubectx jq
gcloud components install gke-gcloud-auth-plugin
```

#### Keycloak admin credentials

You need admin credentials from the `Keycloak Prod Admin` 1Password entry (or
from the `prod-keycloak-server-admin-password` K8s secret in the `ab` namespace).

#### Tailscale VPN

Connect to the Airbyte Tailscale network before proceeding. The GKE cluster's
internal IP is only reachable through the VPN.

### Steps

1. Authenticate to the production GKE cluster and switch context:

   ```bash
   gcloud container clusters get-credentials prod-gke-cluster \
     --region us-west3 \
     --project prod-ab-cloud-proj \
     --internal-ip
   kubectx gke_prod-ab-cloud-proj_us-west3_prod-gke-cluster
   ```

   See the [Accessing GKE Clusters](https://app.notion.com/p/59c708f4f1684e62ae90c84fb7039b8a)
   Notion runbook for full authentication and kubeconfig details. Many engineers
   isolate their production kube config — if you do, use your equivalent command
   (e.g., `export KUBECONFIG="$HOME/.kube/config-prod-gcp"`).

2. Port-forward the Keycloak service:

   ```bash
   kubectl port-forward svc/keycloak-airbyte-keycloak-svc -n keycloak 8180:8180
   ```

3. Copy the admin password to your clipboard:

   ```bash
   kubectl get secret prod-keycloak-server-admin-password -n ab -o json \
     | jq -r '.data.KEYCLOAK_ADMIN_PASSWORD' | base64 -d | pbcopy
   ```

4. Open the admin console and sign in with username `airbyte-admin-20250717`
   and the copied password:

   ```
   http://localhost:8180/auth/admin/master/console/#/airbyte/clients
   ```

   This URL opens the `airbyte` realm's Clients list directly (the realm
   switcher in the default UI is not obvious).

## Updating redirect URIs

To add or modify redirect URIs for the Ops Webapp client:

1. Access the Keycloak Admin Console (steps above).
2. Find and click `airbyte-ops-webapp-client` in the clients list.
3. Under the **Settings** tab, scroll to **Valid Redirect URIs**.
4. Add, edit, or remove URIs as needed.
5. Click **Save** at the bottom.

Changes take effect immediately — no restart or redeployment is required.

## Terraform note

Keycloak realm configuration (SMTP, identity providers, OpenID clients) can also
be managed via Terraform in the `airbyte-platform-internal` repo
(`infra/terraform/modules/keycloak/`). However, the Ops Webapp client was created
manually and is currently maintained through the Admin Console. If the client is
migrated to Terraform in the future, update this document accordingly.
