SMS OTP Authenticator
sms_otp sends a short-lived numeric code to a user's phone number over
SMS. Unlike TOTP, it has no separate enrollment step — at sign-in, O2ID
reads the phone number straight from the user's own attributes, generates
a code, stores its hash, and delivers it through a connection you
configure. The user proves possession of the phone by submitting the code
back.
Requirements
sms_otp needs an sms-provider-category connection to send through.
Today that means twilio — see Connections
for connection basics.
Create the connection:
o2idctl connections create --type twilio --name "Twilio" \
--field accountSid=<account-sid> \
--field authToken=<auth-token> \
--field fromNumber=+15550001111
fromNumber must be in E.164 format (a leading +, country code, no
spaces or punctuation).
Configure SMS OTP
o2idctl authenticators create --type sms_otp --display-name "SMS OTP" \
--connection-id <connection-id>
Fields:
| Field | Default | Description |
|---|---|---|
codeLength | 6 | Number of digits in generated codes |
ttlSeconds | 300 | How long an issued code stays valid |
maxAttempts | 5 | Verification attempts allowed before the code is rejected outright |
cooldownSeconds | 30 | Minimum time between two codes sent to the same user |
attributeKey | phoneNumber | User attribute holding the destination phone number |
The user's attributeKey attribute must already hold a phone number in
E.164 format — a missing or malformed value fails the send instead of
silently dispatching an SMS.
Using SMS OTP authenticator in a flow
{
"sms-otp": {
"type": "authenticator",
"onSuccess": "allow",
"onFailure": "sms-otp",
"properties": {
"authenticatorId": "<authenticator-id>",
"maxAttempts": 5,
"onLockout": "deny"
}
}
}
O2ID sends a code the moment a flow run reaches this node, and expects a
code value on the next Advance call — the same shape as
TOTP. A resend (the run
returning to this node after a rejected code) only dispatches a new SMS
once cooldownSeconds has elapsed since the last one; within the
cooldown window the user re-enters the code from the message they already
received.
See Flows for a complete login flow example.