BuildBaseBuildBase

Usernames

Let people sign in with a username as well as their email, and decide whether every sign-up needs one.

With usernames on, the password form on your hosted sign-in page takes a username or an email, and people choose a username when they sign up with a password or later from your app. Usernames are off until you turn them on, and the address stays the account's identity either way: a username is a second name to sign in with, not a replacement for the email.

Step by step, with screenshots: Set up usernames.

Before you start

Turn them on under User Management → Access → Authentication → Sign-up, in the Usernames card, with Allow usernames. Usernames work with password sign-in, so your client needs the Email/Password method.

Require a username at sign-up, in the same card, makes every password sign-up choose one and stops anyone removing theirs. Accounts made before keep signing in without one. Both switches are username: { enabled, required } on the auth config.

The rules

A username is 3 to 30 characters of lower-case a to z, digits, ., - and _, starting and ending with a letter or digit, with no two dots in a row. Typed capitals are stored lower case, so Ada and ada are the same name. Only Latin letters, so two names that look alike are the same name and nobody can register a look-alike from another alphabet.

Each is unique in your app. These are reserved and nobody may take them: admin, administrator, root, support, help, system, api, null, undefined, owner, staff, security, billing, moderator and buildbase.

The same rules run in the hosted page, the SDK and the server, so a name the form accepts is one the server stores. For a form of your own:

import { isValidUsername, normaliseUsername } from '@buildbase/sdk/react';

normaliseUsername('Ada.Lovelace'); // 'ada.lovelace'
normaliseUsername('admin'); // null: reserved
isValidUsername('ada..l'); // false: two dots in a row

Signing in

The field on the sign-in page reads Email or username while usernames are on. Magic links and email codes still need an address, since they are sent to it.

A username that does not exist, and a wrong password, get the same answer: "Invalid username or password." The page cannot be used to find out which usernames are taken. If you call the API yourself, send username in place of email to POST /api/v1/auth/login.

Choosing one

  • At sign-up. The register page asks for a username beside the password, required or optional as you set it. Other ways of signing up, such as a social provider, a code or a phone, do not ask; those people add one later.
  • From your app. The SDK's Profile screen shows a Username field while usernames are on or the person has one. It offers Remove unless you require one. Hide it with ui.settings.profile.username: false.
  • From your own screen:
await api.setUsername('ada.lovelace'); // { username }
await api.removeUsername();

api is a WorkspaceApi. useSaaSAuth().user.username holds the current one, and AuthApi.getUsernamePolicy(orgId) reads { enabled, required } from your public auth config.

RouteAnswers
PUT /api/v1/public/profile/username{ username }, as stored
DELETE /api/v1/public/profile/username{ success }
RefusalWhen
400 invalid_usernameThe name breaks a rule above
409 username_takenAnother account here has it
400 usernames_offYour app has usernames off
409 username_requiredRemoving it while your app requires one

Turning usernames off never refuses a sign-up that sends one: an older page or SDK that still sends a username is let through, and the name is ignored.

Elsewhere

  • Webhooks. The actor object a delivery carries includes username when the person has one.
  • Importing. An import line can carry username. One that breaks the rules, or is taken here, is left off with a warning and the user is imported without it.
  • Deleting. A deleted account's username is freed with the rest of its data.

Next steps