Releasesv0.1.0

Tenants, users and tokens

Who holds which secret, what each one can call, and how long it lives.

An instance serves one or more tenants. A tenant is a customer of the instance, usually your backend. Each tenant has end users, the people whose data it holds. Two kinds of secret go with them, both sent as Authorization: Bearer <secret>.

Tenant API key · ohs_sk_

Held by your server. Calls the tenant routes: users, tokens, connections and reads.

User token · ohs_ut_

Held by one person's app or agent. Scoped to that user and to upload, connect or read.

A tenant key on a user route, or a user token on a tenant route, gets 403. A user, workout or sleep session of another tenant reads as 404, never 403, so ids do not leak across tenants.

Tenant API keys

The first key comes from ohs admin tenant create --name <name>, or from OHS_BOOTSTRAP_TENANT, which creates a tenant at first start and logs its key once. Keys are stored as SHA-256 hashes: a lost key cannot be shown again, only replaced.

ohs admin tenant create --name acme        # prints the first key once
ohs admin key create --tenant <tenant id>  # add a key, for rotation
ohs admin key list --tenant <tenant id>    # prefixes, created and last used
ohs admin key revoke --tenant <tenant id> --key <prefix>

To rotate a key without downtime, see Rotating secrets.

User tokens

Your server mints a user token for one active user, with the scopes it needs:

curl -s -X POST $OHS/v1/users/$USER_ID/tokens -H "Authorization: Bearer $KEY" \
  -H 'Content-Type: application/json' -d '{"scopes":["upload"],"ttl_seconds":3600}'
# {"token":"ohs_ut_...","expires_at":"...","scopes":["upload"]}
ScopeLets the tokenLifetime
uploadsend device data for that user (POST /v1/ingest/...)1 hour by default, at most 24 hours
readread that user's data over MCPup to 30 days when read is its only scope
connectreserved: no route uses it yet1 hour by default, at most 24 hours

The token is shown once (Cache-Control: no-store) and stored hashed. It stops working at expires_at, or as soon as its user is deleted. Revoking the tenant key that minted it does not end it; ohs admin key revoke with the whole token does.

Keep tenant keys on your server

A tenant key can read every user of the tenant. Never ship it in a mobile app: give the app a user token instead, minted by your backend when the app needs one.

Edit on GitHub

On this page