Skip to main content
Version: Next

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 OIDC prompt parameter on /oauth2/authorizeselect_account shows the chooser, login forces a fresh sign-in that adds an account, none returns login_required/consent_required instead of showing any UI, and consent re-asks for a remembered grant.

  • A way to sign out: POST /t/{tenant}/logout signs out of one account by default, or of every account in the browser with all=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 by GET /export, GET /export/secrets and POST /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-secrets writes them to a separate file, decrypted at export and re-encrypted under the target's own key. Two new scopes, tenant:export and tenant: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 the identity-provider, message-sender, or log-publisher capability plugs into the same internal call sites a compiled-in connector uses. A new connection_call flow node type calls any connection's declared operations synchronously — see Flow Definition Reference. A reference implementation ships at cmd/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 via navigator.credentials.get().

  • An SMS OTP authenticator (sms_otp) and a twilio connection type (category sms-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 choice flow 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_context flow 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 login now uses it.

  • o2idctl config add/config update's API base URL prompt now accepts a tenant appended as /t/{tenant}, so a profile can target a tenant other than system — see Setting up O2ID CLI.

Changed

  • The sessions table gained container_token, created_at and last_used_at columns for multi-account browser sessions. Existing session rows don't carry them, so everyone is signed out once on upgrade.
  • GET /health is 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/connection resource reference moved from a type-specific properties.authenticatorId/properties.connectionId field to a shared top-level id field on every node — see the Node shape reference. Existing flow definitions using the old properties-nested fields need updating.
  • o2idctl login no 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's callbackUrls must now match a redirect_uri exactly, 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, and GET/PATCH /settings no longer have a lifetimes field — 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:assign could 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 o2idctl CLI 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.