Text messages Recommended
Format code texts for automatic fill
End every sign-in code text with the origin-bound line @example.com #123456, using the exact host of the sign-in page.
How to do it
The origin-bound one-time code format, a WICG draft, ties the code to your domain. Phones then offer the code only on that site, which blunts phishing pages that ask for it. Safari on iOS and macOS fills it from the keyboard, and Chrome on Android reads it through the WebOTP API. Put the readable text first and the bound line last. Mark the code field with autocomplete="one-time-code". Let each code expire within 10 minutes.
Example
export const signInCodeText = code =>
`Your ExampleShop code is ${code}. It expires in 10 minutes.\n\n@example.com #${code}`;
// Browser, Chrome on Android: fill the field when the text arrives
if ('OTPCredential' in window) {
const otp = await navigator.credentials.get({ otp: { transport: ['sms'] }, signal: AbortSignal.timeout(120_000) });
document.querySelector('input[autocomplete="one-time-code"]').value = otp.code;
}
import re
BOUND_LINE = re.compile(r"^@example\.com #[0-9]{4,8}$")
def sign_in_code_text(code: str) -> str:
return f"Your ExampleShop code is {code}. It expires in 10 minutes.\n\n@example.com #{code}"
def test_code_text_ends_with_bound_line():
assert BOUND_LINE.match(sign_in_code_text("481920").splitlines()[-1])
How to check
A template test asserts that the last line of every code text matches ^@example\.com #[0-9]{4,8}$.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers notifications playbook: https://agentwranglers.se/playbook/notifications/text-messages/sms-code-autofill.