Changelog
All notable changes to O2ID are documented on this page, most recent first. Each release lists what was Added (new capability) and what Changed (existing behavior that's different from the previous release) — see GitHub Releases for downloadable binaries and the raw commit history behind each tag.
Unreleased
Added
-
Multi-account browser sessions: one browser can now be signed in as several accounts at once (and in several tenants at once). Signing in as a second account adds it instead of silently signing the first one out. New account chooser page at
/t/{tenant}/select-account, and real support for the OIDCpromptparameter on/oauth2/authorize—select_accountshows the chooser,loginforces a fresh sign-in that adds an account,nonereturnslogin_required/consent_requiredinstead of showing any UI, andconsentre-asks for a remembered grant. -
A way to sign out:
POST /t/{tenant}/logoutsigns out of one account by default, or of every account in the browser withall=true. There was no logout endpoint of any kind before — sessions only went away by expiring. -
Config export and import (
o2idctl export/o2idctl import, backed byGET /export,GET /export/secretsandPOST /import): write a tenant's resource servers, roles, connections, authenticators, applications, flows and settings to one portable JSON dump, and re-create them in another tenant on the same instance or a different one. Imports run as a single transaction, remap every cross-resource reference, and take--on-conflict fail|skip|overwrite. Secrets are excluded by default;--include-secretswrites them to a separate file, decrypted at export and re-encrypted under the target's own key. Two new scopes,tenant:exportandtenant:import. -
Connection types backed by a remote HTTP service — register a new connection type without forking or rebuilding O2ID (
o2idctl connection-types create/get/list/update/delete/refresh). O2ID calls out to your service's manifest and invoke endpoints, signed and idempotency-keyed; a registered type declaring theidentity-provider,message-sender, orlog-publishercapability plugs into the same internal call sites a compiled-in connector uses. A newconnection_callflow node type calls any connection's declared operations synchronously — see Flow Definition Reference. A reference implementation ships atcmd/echo-connector. -
A passkey authenticator (
passkey), backed by WebAuthn/FIDO2: sign-in with a device's platform authenticator or a security key, driven automatically by the login portal vianavigator.credentials.get(). -
An SMS OTP authenticator (
sms_otp) and atwilioconnection type (categorysms-provider) for delivering it — a flow node sends a code to the user's phone number and verifies it back, with no separate enrollment step. -
A
choiceflow node type: presents several sign-in options at once (password, an external connection, signing in through an Organization) and lets the client pick which one runs, instead of a fixed linear sequence — see Letting the user choose among several sign-in options. -
An
organization_contextflow node type: shows a "signing in to" banner naming the Organization when a login flow is reached via an Organization's own path — see Signing in through an Organization. -
The OAuth 2.0 device authorization grant (RFC 8628), for clients with no browser of their own —
o2idctl loginnow uses it. -
o2idctl config add/config update'sAPI base URLprompt now accepts a tenant appended as/t/{tenant}, so a profile can target a tenant other thansystem— see Setting up O2ID CLI.
Changed
- The
sessionstable gainedcontainer_token,created_atandlast_used_atcolumns for multi-account browser sessions. Existing session rows don't carry them, so everyone is signed out once on upgrade. GET /healthis deployment-scoped: it is served only at the instance root, and/t/{tenant}/health(which used to answer as well) now returns 404 — see Multi-tenancy.- A flow node's
authenticator/connectionresource reference moved from a type-specificproperties.authenticatorId/properties.connectionIdfield to a shared top-levelidfield on every node — see the Node shape reference. Existing flow definitions using the oldproperties-nested fields need updating. o2idctl loginno longer uses the authorization code + PKCE flow. It uses the device authorization grant instead, printing a code to confirm in a browser. As part of this, O2ID no longer special-cases loopback (127.0.0.1/::1/localhost) redirect URIs to ignore the port — every application'scallbackUrlsmust now match aredirect_uriexactly, port included.- Removed tenant-level lifetime overrides for access/refresh tokens,
authorization codes, sessions, and login/consent transactions.
tenant-settings update's six lifetime flags (--access-token-lifetime, etc.) are no longer accepted, andGET/PATCH /settingsno longer have alifetimesfield — see Application settings for the per-application flags that remain the only override mechanism. - Assigning a role, or adding a scope to an existing role, now requires the
caller to already hold every scope being granted — previously a caller
with only
roles:assigncould grant any role, including one carrying*, to any user or themselves. See You can never grant a scope you don't hold.
v0.0.1 — 2026-08-22
Initial pre-release.
Added
- Core OAuth 2.0 / OpenID Connect: authorization code, client credentials, and refresh token grants, PKCE, pushed authorization requests, and token exchange.
- Multi-tenancy with nested Organizations, shared applications, and cross-tenant grants.
- User, role, application, resource server, and agent/mandate
management, each with a REST API and
o2idctlCLI coverage. - Tenant-authored flows: a graph-based engine for login, step-up, and other identity journeys, with authenticator, condition, script, webhook, connection, and credential node types.
- Authenticators: password, TOTP, and federated sign-in through external OIDC connections.
- Verifiable Credentials: OID4VCI issuance and OID4VP verification.
o2idctl, a management CLI covering the full REST API surface.- A JavaScript SDK.
- Docker image and self-hosted deployment guides, including pluggable storage backends.