Skip to content

Login (OIDC)

The admin cockpit (/cockpit/) uses one password. Traders sign in to the separate trading app at /trade/ through an OpenID Connect provider — Keycloak, Okta, Auth0, Entra ID, Google and so on. A signed-in trader sees only the portfolios their principal is granted.

Login is off by default: with no [auth.oidc] block, /auth/* and /trade/ return 404 and nothing else changes.

  1. At your provider, register a confidential client with the redirect URI {public_base_url}/auth/callback, e.g. https://oms.example.com/auth/callback.

  2. Add the block to oms.toml:

    [auth.oidc]
    issuer = "https://idp.example.com/realms/oms"
    client_id = "oms"
    public_base_url = "https://oms.example.com"
  3. Put the client secret in the environment — never in oms.toml:

    Terminal window
    OMS_OIDC_CLIENT_SECRET=...

    A .env next to oms.toml works (see Config file locations).

  4. Restart the OMS.

The first time someone signs in, the OMS creates a principal for them automatically, keyed by the provider’s subject — and with no grants. They can sign in but see and trade nothing until an admin grants that principal a portfolio (on the cockpit’s Principals page, or POST /admin/principals/{id}/grants). An existing service or strategy principal, or a disabled one, can never be taken over by a login.

If the provider is misconfigured or unreachable, login stays off for that run and the error is logged; order routing and the cockpit are unaffected.

To admit only members of a group, require a claim in the ID token:

required_claim = "groups"
required_claim_value = "oms-traders"

Both keys are needed for the check to apply.

A trader’s session ends after idle_ttl_minutes without activity (default 30) and after absolute_ttl_hours regardless (default 12).

The session cookie must be marked Secure. So unless both the bind address and public_base_url are loopback, public_base_url must start with https:// — the OMS refuses to start otherwise.

The usual setup is a loopback bind with TLS terminated in front: a reverse proxy (nginx, Caddy) or tailscale serve, with public_base_url set to the HTTPS address users open.

A clone of the repository includes a disposable Keycloak with a ready-made realm. It is for testing only:

Terminal window
docker compose --profile oidc up -d keycloak
[auth.oidc]
issuer = "http://localhost:8090/realms/oms-dev"
client_id = "oms"
public_base_url = "http://localhost:3001"
Terminal window
OMS_OIDC_CLIENT_SECRET=oms-dev-secret

Sign in at http://localhost:3001/trade/ as trader / trader.