Skip to main content
Version: Next

Authenticators

An authenticator is a tenant-configured instance of an authentication factor type. It can stand alone, or point at a connection for delivery-based factors such as email or SMS one-time codes.

This release ships the authenticator foundation plus a built-in TOTP authenticator and a delivery-based SMS OTP authenticator. TOTP enrollment data is encrypted per tenant, and verified TOTP enrollments can be used by authentication flows; SMS OTP needs no enrollment step, reading the destination phone number straight from the user's own attributes.

Authenticators vs. connections

A connection is a credentialed reference to an external provider — an SMS gateway, an email provider, an external identity provider. An authenticator is different: it's what actually challenges and verifies a user during sign-in (a one-time code, a passkey, or another factor-specific proof). Some authenticator types have nothing to connect to at all, while others optionally point at a connection purely for delivery. If a factor type needs to send something, it wraps a connection; if it doesn't, it stands alone.

Multiple authenticators of the same type

Nothing stops you from creating more than one authenticator of the same type in a tenant (the only uniqueness rule is that display names must be unique). This is genuinely useful for delivery-based types: if you have two email connections — say, two providers, or one per region — you'd typically configure one email_otp authenticator per connection, each with its own display name and delivery settings.

For non-delivery types, there's usually little reason to configure more than one — most tenants will only ever need a single instance of each.

Built-in totp

Every tenant gets a ready-to-use TOTP authenticator, ID totp, with no setup required — a flow can reference authenticatorId: "totp" immediately. It uses fixed defaults (issuer "O2ID", 6 digits, 30-second period, no progressive enrollment) and always appears first in o2idctl authenticators list/GET /authenticators.

It's virtual: it isn't created via authenticators create, and authenticators update/authenticators delete reject it. If you need different settings — a different issuer name, digit count, or progressive enrollment — create a separate totp-type instance with its own ID instead of trying to modify the built-in one; both can coexist.

note

Managing authenticators requires a role with the authenticators:read/authenticators:create/authenticators:update/ authenticators:delete scopes — see Managing Roles for how to create and assign roles.

Discovering available types

o2idctl authenticators list types

Each entry describes an authenticator type's type key, category, and configSchema. The schema tells you which fields to pass via --field when creating an authenticator, and which fields are secret.

Creating an authenticator

o2idctl authenticators create --type <a type from "authenticators list types"> --display-name <name> \
--field <configField>=value --field <secretField>=secret-value

--field is repeatable and carries both non-secret configuration and secret values in one set. The service splits them before storing the authenticator, encrypting only fields marked secret in the type's configSchema. A --field value is parsed as JSON when possible (so --field digits=6 or --field caseSensitive=true carry a number/bool rather than a string), otherwise treated as a plain string.

The response never includes secret values:

{
"id": "a3f2d1c0b9e8d7c6a5f4e3d2c1b0a998",
"type": "...",
"category": "...",
"displayName": "Production factor",
"config": { "...": "..." },
"secretKeys": ["apiKey"],
"enabled": true,
"createdAt": "...",
"updatedAt": "..."
}

Delivery-based authenticators may pass --connection-id pointing at an existing connection.

Listing and inspecting authenticators

o2idctl authenticators list
o2idctl authenticators get <id>

list (unlike list types) returns the tenant's own configured authenticator instances — same shape as create's response, secret values omitted.

Updating and deleting

o2idctl authenticators update <id> --display-name "Production factor"
o2idctl authenticators delete <id>

--field on update is merged key-by-key into the existing field set, so you can rotate one secret without resubmitting every current secret value. --display-name, --connection-id, and --enabled only change when explicitly supplied.

API Reference

See the API Reference for the full request/response schemas.