Sign-in and users
People sign in to the Control Plane and the tenant portal without a password: with a code that comes by e-mail, or with a passkey — Face ID, Touch ID, a fingerprint, Windows Hello or a key from a password manager. The platform keeps the accounts and their roles itself.
How people sign in
- On the sign-in page the person enters their e-mail and gets a letter with a six-digit code.
- The code is valid for 10 minutes and allows five attempts; a new one can be asked for after a minute.
- After signing in with a code, a device that can keep passkeys offers to save one. Next time the passkey is enough — the browser offers it right in the e-mail field. The code stays as a fallback.
Passkeys are listed in the profile (account menu → "Profile"), where they are added and removed. The profile also shows the browsers the person is signed in with now and their sign-in history.
The sign-in form does not tell whether an account with the address exists: the letter goes only to addresses that have one, and the answer is the same for any.
| A session lasts | |
|---|---|
| Platform user | 12 hours, then sign in again |
| Tenant user | 30 days, extended while it is used |
Signing out ends the session on the server, not only in the browser.
Sessions and devices
The profile's "My devices" lists the browsers the person is signed in with now: the device, the IP address, when they signed in and when the last request came. The session on any other device can be ended, and "End all the others" leaves only the current one.
Administrators see the same for their people: the user list opens a "Sessions and sign-ins" window — the person's active sessions with "End all sessions", and their latest events. In the Control Plane these are the lists of platform users and of a tenant's users; in the tenant portal, the "Users" page.
A browser whose session was ended learns it on its next request: the person lands on the sign-in page, which says the session has ended — and, when a sign-in on another device pushed it out, says that too.
SIGN_IN_MAX_SESSIONS limits how many sessions one person may have at once: past the limit, a new sign-in ends the session unused the longest. The default is 0, no limit.
The letter about a sign-in from a new device
When an account is signed in to from a browser it has not been signed in from before, a letter goes to its address: when, from which device and IP address, and how. It also says what to do if it was not the account's owner: open the profile, end the sessions on other devices and tell the administrator. The letter has no links, like the code's letter.
A browser is recognised by a random id in a cookie that lives 400 days, and "not signed in from before" means not within the time the history is kept. The very first sign-in sends no letter: the person has just been invited. In a browser whose cookies were cleared, a sign-in counts as new again.
Sign-in history
The platform records sign-ins — with a code by e-mail, a passkey or through a provider — failed attempts, sign-outs and ended sessions: when, who, from which device and IP address and, for an ended session, why and who ended it. The failed attempts recorded are a wrong code, an unknown passkey, and a sign-in through a provider with an address that has no account. Code requests and refusals for rate limits are not recorded: they can be sent endlessly, and the history would fill up with them.
- People see their own history in the profile.
- In the Control Plane, a platform administrator's "Journals" has two tabs: "Actions" and "Sign-in history". The second holds the history of all platform and tenant users, filtered by person, event, IP address, period and tenant.
- In the tenant portal, the tenant's owner and administrators have the same "Journals", with the history of the tenant's users.
From a line of the history, "Actions that day" opens the "Actions" tab filtered to that person and that day. "Full history" in the "Sessions and sign-ins" window opens the history tab filtered to the person.
The history is kept for SIGN_IN_HISTORY_DAYS days, 180 by default; older records are deleted.
Accounts
The e-mail address is the account: on the whole installation an address belongs to one person.
- Platform users are added by a platform administrator in the Control Plane, under "Platform users": a name, an e-mail and roles. Administrators do not block, delete or demote their own account — another administrator does; the last active administrator stays one.
- Tenant users are added by the platform on the tenant's page, or by the tenant in its own portal, within its rights.
A new user is sent an invitation: a letter with a link to the sign-in page. A tenant user lands on the sign-in page in their tenant's look, and their letters come in the same look, see Branding.
Blocking and changing the address end all of the person's sessions at once; deleting also removes their passkeys.
Signing in through other systems
When the staff already have accounts in the organisation's sign-in system — Keycloak, ADFS, Azure AD or another with OpenID Connect — it can be added as a button on the sign-in page of both portals. A platform administrator does this in the Control Plane, under "Sign-in providers": the button's caption, the provider's address (issuer), the Client ID and, for a confidential client, its secret. At the provider, register the client and the callback addresses the Control Plane shows once the provider is saved — one for each portal.
The provider confirms who the person is and does not make an account. It signs in to the account whose address the provider says it has confirmed; from the first sign-in that account is linked to the person at the provider and found by that link from then on, even if their e-mail there changes. Accounts are still made in the Control Plane and the tenant portal.
Signing in through providers needs the backend's SECRETS_KEY — the same one for the Control Plane and the tenant portal: it encrypts the client secret in the shared database and protects the sign-in itself.
The first administrator
While the platform has no users, nobody can sign in. The first administrator is added on the server, in the backend's environment:
bash
python -m app.tools.users add admin@example.com --name "Anna Petrova"They sign in to the Control Plane with a code like everyone else and add the rest themselves. The same command adds an administrator when the only one has lost access to their mailbox. python -m app.tools.users list lists the platform users, remove <email> removes one.
What the installation needs
| Backend setting | Why |
|---|---|
CP_URL, TP_URL | The portals' addresses, as users open them. Changes are accepted from their pages only, passkeys work at them, invitations lead to them. Set both — for the Control Plane and for the tenant portal alike: from the Control Plane, a tenant user's invitation leads to the tenant portal |
SMTP_HOST, SMTP_PORT, SMTP_SECURITY, SMTP_USER, SMTP_PASSWORD, SMTP_FROM | The installation's mail server: codes and invitations go out through it. SMTP_SECURITY is ssl (port 465), starttls (587) or none (a local relay) |
MAIL_LANGUAGE | The language of invitations: ru or en. A code's letter is written in the sign-in page's language |
SIGN_IN_MAX_SESSIONS | How many sessions one person may have at once; past that, a new sign-in ends the one unused the longest. 0 — no limit, the default |
SIGN_IN_HISTORY_DAYS | How many days the sign-in history is kept, 180 by default |
Without mail nobody gets a code
Without a mail server, signing in with a code does not work — the sign-in page says the letter with the code could not be sent — new users get no invitations, and nobody hears of a sign-in from a new device. Mail can be left out only when everyone signs in through a provider.
Passkeys work on a domain name only
The browser binds a passkey to the site's address, so passkeys work on a domain name over HTTPS and not on an IP address. A passkey saved in the Control Plane does not work in the tenant portal — each address has its own keys.
Code requests are limited: at most one a minute and five an hour per address, twenty an hour from one IP. The backend serves the portals itself, and the browser reaches the API at the same address — there is no separate sign-in server.