Passwordless sign-in
Purpose: let your users sign in with nothing but access to their inbox. Two flows, independently switchable, both built into your tenant's hosted sign-in page — no code to write and nothing to render yourself.
Email code: the sign-in page emails a 6-digit code and the user types it into the same page. A code is single-use and expires after 10 minutes.
Magic link: the sign-in page emails a link. Opening it shows a confirmation button — so a mail client or security scanner that prefetches the URL cannot spend it — and confirming completes the sign-in on that device. A link is single-use and expires after 15 minutes; an expired one sends the user back to the sign-in page to request a fresh one.
The same rules as every other sign-in
Both flows land in the same completion path as password and social sign-in, so passwordless is not a side door:
Multi-factor authentication still applies. A user who owes a challenge under your MFA policy is challenged before any session exists — an emailed code does not stand in for a second factor.
Ineligible accounts are refused indistinguishably. A disabled or deleted account answers exactly like a wrong code or a dead link, so the flow never confirms whether an address has an account.
Requesting a code or link never reveals anything either. The response is the same whether or not the address is known, and requests are rate-limited per source and per address.
A passwordless session is never a remembered session. An emailed credential is forwardable and often opened on a device the account holder does not control, so the session either flow creates ends with the browser session and is bounded by your tenant's session lifetimes either way — deliberately, and regardless of your remember-me settings. Password sign-in keeps its explicit remember-me checkbox.
Turning the flows on and off
Each flow is its own tenant-level switch, on by default, edited in the dashboard under Security → Sign-in methods or through the management API:
| Method | Path | Scope |
|---|---|---|
PATCH | /api/identity/tenants/{id} | identity:tenants:write |
The authMethods object you send is merged into the current setting — a
switch you omit keeps whatever it is set to, so you can send just the one you
are changing. A policy that would leave every method off is refused, and the
check runs on the merged result: turning off the last method your tenant still
has is a 400 whether you name all four switches or only that one.
A tenant can go fully passwordless by turning the password method off and keeping every other method on — the hosted pages follow the policy, so the password form disappears everywhere it appears, account creation included:
const tenantId = Deno.env.get("UDIBO_TENANT_ID");
const response = await fetch(
`https://www.udibo.com/api/identity/tenants/${tenantId}`,
{
method: "PATCH",
headers: {
authorization: `Bearer ${Deno.env.get("UDIBO_API_TOKEN")}`,
"content-type": "application/json",
},
body: JSON.stringify({ authMethods: { password: false } }),
},
);
if (!response.ok) throw new Error(`update failed: ${response.status}`);Naming only password is the whole request: emailCode, emailLink and
social keep whatever they are set to. Send all four if you would rather be
explicit — the result is the same when the values agree.
{id} is your tenant's id — the same one in your dashboard URL — and the token
must hold administrative authority over that tenant.
Administrator credentials required. These management calls use the
credential associated with an authorized Udibo dashboard session. A machine
credential issued to an application in your own tenant is not accepted on
/api/identity/…. Use the dashboard or an approved administrator workflow; keep
administrator credentials out of your application integration.
Last verified 2026-09-06.

