> For the complete documentation index, see [llms.txt](https://docs.envector.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.envector.io/1.5.x/operations-and-management/authentication/keycloak.md).

# Keycloak / OIDC

enVector authenticates callers through an OIDC identity provider. The bundled deployment ships a local **Keycloak** instance for quick start. **If your organization already operates an OIDC-compatible IdP (Keycloak, Okta, Azure AD/Entra ID, an LDAP/AD-backed provider, etc.), using that existing IdP is recommended** — the bundled local Keycloak is intended for getting started and for environments without an existing IdP. This page covers integrating Keycloak and the claims enVector expects; for day-2 auth operations (token issuance, rotation, password changes, troubleshooting) see [Authentication](/1.5.x/operations-and-management/authentication.md).

## Overview

The Endpoint verifies a signed JWT on each call and authorizes it against enVector's role model. A valid token must carry:

* **`principal_id`** — the caller identity (per-user attribute)
* **`tenant_id`** — the tenant the caller belongs to
* **`envector_roles`** — the realm roles granted to the caller
* an **audience** trusted by the Endpoint (defaults: `envector-cli`, `envector-api`)

Keycloak issues these as a signed JWT; the Endpoint validates the signature via the realm's JWKS endpoint.

## Enabling the local Keycloak overlay

Start the stack with the Keycloak overlay (via the helper script or Docker Compose directly):

```bash
./scripts/start_envector.sh --kms --keycloak --audit --console
```

Confirm the realm is discoverable (returns HTTP 200):

```bash
curl -fsS "http://127.0.0.1:${KEYCLOAK_HOST_PORT:-8082}/realms/${KEYCLOAK_REALM:-envector}/.well-known/openid-configuration" \
  | jq -e '.issuer' >/dev/null
```

The default realm is `envector` (`KEYCLOAK_REALM`) on host port `8082` (`KEYCLOAK_HOST_PORT`).

## Seeding realm roles and users

Seed the realm with strong passwords from `.env` (idempotent):

```bash
set -a; source ./.env; set +a

./scripts/auth/seed_local_keycloak_users.sh \
  --port "${KEYCLOAK_HOST_PORT}" \
  --realm "${KEYCLOAK_REALM}" \
  --admin-user "${KEYCLOAK_BOOTSTRAP_ADMIN_USERNAME}" \
  --admin-pass "${KEYCLOAK_BOOTSTRAP_ADMIN_PASSWORD}" \
  --user-password "${KEYCLOAK_LOCAL_USER_PASSWORD}" \
  --tenant-id "${KEYCLOAK_LOCAL_TENANT_ID}"
```

Seeded operational users (all using `KEYCLOAK_LOCAL_USER_PASSWORD`):

| User             | Granted roles                               | Purpose                                               |
| ---------------- | ------------------------------------------- | ----------------------------------------------------- |
| `envector-admin` | `security` + `realm-management/realm-admin` | Realm administration + security operations            |
| `security`       | `security`                                  | Audit / Admin API                                     |
| `ops`            | `ops`                                       | Operational queries (`/admin/indexes`, `/admin/keys`) |
| `app`            | `app,keymanager,topk`                       | Application SDK calls                                 |
| `app-a`          | `app,keymanager,topk` (tenant-a)            | Multi-tenant verification                             |
| `app-b`          | `app,keymanager,topk` (tenant-b)            | Multi-tenant verification                             |
| `keymanager`     | `keymanager`                                | Key issuance/management                               |
| `topk`           | `topk`                                      | TopK search permission                                |
| `pubkey-reader`  | `pubkey-reader`                             | Public-key lookup                                     |
| `audit-only`     | `audit-only`                                | Audit read-only                                       |

The realm roles map directly onto the enVector and KMS capability model — see [KMS Architecture → Identity provider](/1.5.x/key-management/managed-kms.md#identity-provider-keycloak).

## Multi-tenancy

The seed assigns a tenant via `KEYCLOAK_LOCAL_TENANT_ID`, written into each user's `tenant_id` attribute. Tokens then carry `tenant_id`, and requests scope to that tenant (e.g. the `x-tenant-id` header on audit queries). Seed additional tenants (as with `app-a`/`app-b`) for multi-tenant setups.

## Client scopes

Beyond the default OIDC scopes (`openid profile email`), enVector defines audit scopes that must be requested to reach the audit API:

* `audit:read` — read audit events
* `audit:export` — export audit events

Request them when issuing an audit token, e.g. `--scopes "openid profile email audit:read audit:export"`. See [Audit](/1.5.x/operations-and-management/audit.md).

## Adding users and roles

When adding users beyond the seed, align attributes and roles with enVector's conventions:

* **Required attributes:** `principal_id`, `tenant_id`
* **Realm role candidates:** `security`, `ops`, `app`, `keymanager`, `topk`, `pubkey-reader`, `audit-only`, `audit-exporter`
* **Trusted audiences:** `envector-cli`, `envector-api` (defaults)

In the admin console: `envector` realm → **Users → Add user** → set `principal_id`/`tenant_id` under **Attributes** → set a password under **Credentials** (`Temporary` OFF) → grant roles under **Role mappings**. To automate, follow the `ensure_user` pattern in `seed_local_keycloak_users.sh` using `kcadm.sh`.

## External IdP integration (reference)

To use your organization's IdP (LDAP, AD, an OIDC provider, etc.) in production:

1. Register the IdP under the `envector` realm → **Identity providers** or **User federation**.
2. Configure a mapper so that `principal_id` and `tenant_id` are included in the token.
3. Confirm the Endpoint's `ENVECTOR_AUTH_ALLOWED_AUDIENCES`, `ENVECTOR_AUTH_ROLE_CLAIM`, and `ENVECTOR_AUTH_PRINCIPAL_CLAIM` match the external IdP's claims.

If your organization already runs an IdP, integrating it is recommended over maintaining a separate local Keycloak. Reserve the bundled local Keycloak for quick start or for environments that have no existing IdP.

## Data persistence

In the bundled `docker-compose.keycloak.yml`, the user-data volume mount is commented out by default. In production, enable it so user and role changes persist across restarts:

```yaml
# docker-compose.keycloak.yml
services:
  keycloak:
    volumes:
      - ${DOCKER_VOLUME_DIRECTORY:-./volumes}/keycloak/data:/opt/keycloak/data
      - ${START_ENVECTOR_COMPOSE_DIR:-.}/keycloak/import:/opt/keycloak/data/import:ro
```

Without persistence, you must re-run the seed whenever the container restarts or the image is updated.

## SDK connection

To connect the Python SDK with a Keycloak-issued token, see [Connection](/1.5.x/sdk-user-guide/initialize/connecting-to-the-service.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.envector.io/1.5.x/operations-and-management/authentication/keycloak.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
