OBLETHdocs

Connect the gateway

Let Chat stream through obleth as each signed-in person, using short-lived tokens the gateway verifies against Chat's public keys.

3 min readUpdated for Chat 0.5.2Edit on GitHub

Chat needsThe gateway URL and a signing key
Gateway needsChat as a trusted JWT issuer
Tokens live5 minutes
Shared keysNone

Chat never holds a gateway API key. For each request it signs a five-minute RS256 token whose subject is the person's internal account ID, and only Chat's server sends it. The gateway checks the token against Chat's public keys and accounts for the request under that identity, so every person has their own usage and fairshare position. See Identity tokens for the gateway side.

Set it up

setup.sh makes the signing key, configures Chat and prints the gateway entry, so with it only the last two steps are left: trust Chat in the gateway and check it.

  1. 1

    Make a signing key

    Generate a dedicated RSA key outside source control:

    umask 077
    openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 \
      -out /secure/path/obleth-chat-signing.pem
    
  2. 2

    Configure Chat

    Set the gateway's origin (without /v1) and the key file. Both are needed, or neither.

    OBLETH_CHAT_GATEWAY_URL=http://obleth-gateway:8080
    OBLETH_CHAT_GATEWAY_SIGNING_KEY_FILE=/secure/path/obleth-chat-signing.pem
    OBLETH_CHAT_GATEWAY_ISSUER=https://chat.example.edu
    OBLETH_CHAT_GATEWAY_AUDIENCE=obleth
    

    The issuer defaults to OBLETH_CHAT_ORIGIN and the audience to obleth. Restart Chat; it publishes its public key at /.well-known/jwks.json.

  3. 3

    Trust Chat in the gateway

    Merge this entry into the gateway's existing OBLETH_JWT_ISSUERS array (Helm: obleth.jwtIssuers), keeping any other issuers:

    {
      "issuer": "https://chat.example.edu",
      "jwks_url": "http://obleth-chat:8085/.well-known/jwks.json",
      "audience": "obleth",
      "algorithms": ["RS256"],
      "subject_claim": "sub",
      "identity_claims": ["username"],
      "tenant": "chat-users",
      "jit_provision": true
    }
    

    Pick an existing tenant that has the models, budgets and policy Chat's users should get. If the tenant doesn't exist, the gateway creates it on the first request with default policy and raises an Identity tenant created alert. The issuer and audience must match Chat's exactly, and the gateway must be able to reach the JWKS URL. Plain HTTP is fine for an in-cluster URL.

    Start Chat before you restart the gateway with the new entry. The gateway's log then shows jwks loaded issuer=https://chat.example.edu.

  4. 4

    Check it

    Sign in to Chat. The model picker lists the gateway's models, and Settings › Administration › Models shows the catalog to publish. See Models, groups and limits.

    The picker shows every chat model the tenant may use, including internal ones such as a router classifier or a test model. Narrow the tenant's model allowlist in the gateway, or hide those models in Models.

What Chat sends

  • Discovery: GET /v1/models, live, filtered by the models each person may use.
  • Generation: POST /v1/chat/completions with the stored history, streaming with usage chunks. Chat records x-obleth-session-id and x-obleth-request-id with each reply, so you can find its trace in the gateway's request logs.
  • Effort: the thinking effort as reasoning_effort. With Auto, Chat sends model: "auto" and tells the router how hard the request is: None and Low send x-obleth-effort: low, High sends high, and Medium leaves the router to judge.
  • Embeddings: for Knowledge, POST /v1/embeddings with the embedding model.

Stopping a response cancels the upstream request. Chat follows no redirects from the gateway, so a bearer token can't be sent somewhere unexpected.

To show administrators a link to the gateway's dashboard, set OBLETH_CHAT_ADMIN_GATEWAY_URL to its public URL.

Several replicas and key rotation

Every Chat replica must use the same signing key and issuer. Chat publishes one key at a time; staged rotation with two keys isn't implemented yet. Replacing the key also makes saved connection tokens unreadable, because they're encrypted with a key derived from it, so people then enter them again.

How Chat users map to tenants

All Chat identities share the tenant in the issuer entry. Distinct token subjects give each person their own identity and accounting inside it. Chat adds its own per-person and per-group model access on top; Auto is limited by the tenant's allowlist and the gateway's Auto-eligible models.

In the gateway's keys and usage, each person appears as an identity key named <Chat account ID>-cli, with their Chat username in its identity claims ({"username": "…"}). The account ID is a UUID, not a name, so match keys to people through that username claim. Accounts created by OIDC sign-in get a generated username of the form oidc_<id>.