Skip to main content

Authentication

The CLI has two credentials. Both are stateless: the server never issues a session cookie, the credential is sent on every call, and scopes are checked per resource.

CredentialBest forHow
Login tokenPeople at a terminallumo login --org <slug> (device authorization: you approve the sign-in in a browser on any device)
API keyCI, scripts, AI agentsLUMO_API_KEY=lmk_… LUMO_ORG=<slug>

Not sure what the CLI is about to use? lumo whoami tells you, and lumo doctor checks it against the server.

How the browser sign-in works

Device authorization lets a keyboard-only client sign in through a browser on any device: the CLI shows a short code, you approve it in the portal, and the CLI receives a token. The CLI always sends an explicit scope parameter (the list of what the token may do), so the token carries exactly what you asked for rather than everything the client is allowed.

Do this first​

lumo login --org acme-corp # approve in the browser
lumo doctor # every check should be ✓
lumo users list # any resource command

Login tokens and scopes​

lumo login requests these scopes unless you narrow them:

openid profile email admin

admin is the blanket Admin API scope. Every lumo resource command (users, roles, apps, agents, webhooks, settings, …) calls the Admin API, which accepts an OAuth token only when it carries admin or an admin:<resource>:<read|write> scope and the signed-in user holds settings.manage in the organization.

For a least-privilege session, request resource scopes instead:

lumo login --org acme-corp --scope openid,admin:users:read,admin:audit:read

The granted scopes are stored with the credentials and shown by lumo whoami. A command that needs more answers 403 with the missing scope named, plus the exact lumo login --scope … to fix it.

The first lumo login against an organization lazy-creates a public OAuth client, lumoauth-cli:<slug>, allowing the default scopes above. An administrator can narrow that client's allowed scopes in the portal, under Applications → Provided by LumoAuth tab → LumoAuth CLI (first-party) → Configuration → Allowed scopes, to force least-privilege CLI sessions; requesting a scope the client does not allow fails with invalid_scope and a hint.

The Allowed scopes section on the Configuration tab of the LumoAuth CLI application

Stored credentials​

# ~/.lumoauth/credentials.yaml — managed by lumo login / logout / profile (0600)
version: 2
current_profile: default
profiles:
default:
base_url: https://app.lumoauth.dev
org_id: acme-corp
access_token: eyJhbGciOi...
refresh_token: ...
expires_at: 2026-09-16T17:00:00Z
token_type: Bearer
scopes: [openid, profile, email, admin]

Refresh​

Access tokens live one hour; the refresh token lives 30 days. The CLI refreshes silently before a request when the token has expired, and once more when the server answers 401 (revoked or clock skew), then retries. Only when the refresh token itself is gone do you see:

Error: stored credentials have expired and refresh failed.
Re-authenticate with 'lumo login', or switch to a long-lived API key: …

API keys​

export LUMO_API_KEY=lmk_your_key_here
export LUMO_ORG=acme-corp
lumo users list -o json

Create keys in the portal under Applications & developer tools → API keys → Create API key (/orgs/<slug>/portal/settings/api-keys). The full key is shown once, on the next page.

The Create API key form with the key details and the permission checkboxes

A key carries the per-resource scopes you tick (admin:users:read, admin:webhooks:write, …). Rules the server applies:

  • list and get commands need the resource's :read scope; create, update and delete need :write. Scopes match exactly, so a job that does both needs both.
  • a scope for one resource never unlocks another: admin:webhooks:read gets 403 on lumo users list.
  • the key's creator must stay active and hold the permission each endpoint requires (for example users.view for lumo users list); otherwise the call gets 403 with required_permissions.
  • the key is sent as Authorization: ApiKey lmk_… (the Admin API also accepts an X-API-Key header).

One key per job, with only the scopes that job's commands need. The per-command list is in the README.

Which credential is used​

For each command the CLI picks, in order:

  1. the login token of the active profile, when it targets the same organization as the command (refreshed if needed);
  2. otherwise the API key from --api-key, LUMO_API_KEY or ~/.lumoauth/config.yaml;
  3. otherwise the command exits with code 2 and a hint.

The login token wins for its own organization so that a stale key for another organization is never sent by accident. To force the API key, run the command against an organization the profile is not logged in to, or lumo logout.

--org, LUMO_ORG and the active profile decide the organization; lumo whoami shows the result.

What each credential can reach​

CredentialAdmin API (lumo resource commands)Portal or account pages
Login token with admin (default)Yes, within the user's own permissionsNever
Login token with resource scopesOnly those resources and levelsNever
API keyOnly the resources and levels its scopes nameNever

Errors you may see​

MessageMeaningFix
403 … required_scopesThe credential lacks a scope the command needsFollow the printed hint: lumo login --scope … or create a key with that scope
403 … missing required permission (body lists required_permissions)The signed-in user, or the key's creator, lacks that resource permissionAsk for the listed permission; settings.manage alone is not enough
401 or 403 with a key that used to workKey revoked, its creator was deactivated, or the creator lost the endpoint's permissionCreate a key under an active administrator who holds it
invalid_scope on lumo loginThe organization narrowed the CLI client's scopesNarrow --scope or ask an admin to allow the scope
exit code 2, not authenticatedNo usable credentiallumo login or set LUMO_API_KEY

lumo doctor reproduces most of these before you hit them. See Credentials and access model for the rules behind them.

Standards used on this page​

Plain nameStandard
Device authorization (sign in on another device)RFC 8628

See the standards reference for what each one covers and how LumoAuth uses it.