Users and login¶
This page describes who can sign in to the byro Office, how sign-in works, and how you manage user accounts. For multi-factor authentication, see the dedicated page MFA; for server-side operation (TLS, the secret key, container privileges) see Security baseline.
Permission model¶
byro distinguishes three kinds of accounts through the two flags is_staff
and is_superuser:
is_staff |
is_superuser |
Office and API | Settings, registration form, users, log |
|---|---|---|---|
| no | no | no | no |
| yes | no | yes | no |
| no | yes | yes | yes |
| yes | yes | yes | yes |
- No flag: the account can neither sign in to the Office nor use the authenticated API.
- Staff (
is_staff): regular access to the Office - members, finances, documents, mails, the own profile - and to the API. - Superuser (
is_superuser): everything staff may do, plus the administrative functions, marked superuser only in this documentation: the initial setup, the general settings, the registration form, the audit log and user management. A superuser can always sign in, even withoutis_staff, so an inconsistent combination of flags cannot lock a superuser out.
These rules are enforced on the server, not only by hiding menu entries. A
staff account that opens a superuser-only page directly gets an error page
(HTTP 403). An account that loses both flags while it is signed in is signed
out with its next request to a protected page. Pages that need no login
(the login page, member pages, /log/info) do not end the session; an API
token of the account stops working immediately.
Warning
The model is deliberately small. There are no finer-grained roles: no read-only access and no restriction to individual areas such as finances or member management. Every staff account sees and edits all members, finances and mails. Weigh this before enabling OIDC auto-provisioning or creating accounts.
Plugins
Plugins that add pages to the "Settings" menu have to restrict them to superusers themselves. byro hides those menu entries from staff, but it cannot protect the pages of a plugin that has not been adapted yet: such a page stays reachable for staff through its direct address. See Settings entries are superuser only.
Existing installations¶
Before this permission model was introduced, every account had unrestricted
access to the whole Office, including settings and user management. To keep
exactly that access, the update sets is_staff and is_superuser for
every existing account, including accounts created through OIDC. Nobody
loses access through the update.
After updating, review "Settings → Users" and remove the superuser status from the accounts that should only have regular access. The migration itself does not write an audit log entry, and migrating backwards does not restore the previous flag values.
Keep a local break-glass superuser¶
Inside the Office, a superuser cannot remove their own superuser status, and only superusers manage accounts, so at least one superuser always remains. This guarantee ends at the Office: an account can still be changed on the server (shell, database), and with OIDC group synchronization the identity provider can remove the superuser status of every account that signs in through OIDC (see Synchronizing permissions).
Keep at least one local superuser account with a password that does not
depend on OIDC, for example the account created during installation with
createsuperuser. If no superuser is left, see
Account recovery.
First login¶
Superuser only. As long as name, sender address and notification address (Settings → General, see Settings) are not set, byro redirects every signed-in account (except during the MFA flow) to the initial setup. Only a superuser can complete it; a staff account, for example one just created through OIDC, sees an error page telling it that a superuser has to finish the setup first. Logging out and signing in with another account (password or OIDC) stays possible while the setup is incomplete.
Password login¶
The default: username and password, checked against the local account. An account with no usable password (see "Disable password" below) cannot sign in with a password - only with one of the other enabled methods.
OIDC/SSO login¶
If [oidc] issuer_url is set (see
Configuration), the login page
also shows an SSO button. The flow:
- byro redirects to the OIDC provider (authorization code flow with
stateandnonce). - After a successful sign-in at the provider, byro validates the ID token
(signature against the provider's JWKS, issuer, audience, expiry,
nonce). - If
staff_grouporsuperuser_groupis set, byro reads the groups of the user: from thegroupsclaim of the ID token if the token has one, otherwise from the userinfo endpoint. A claim that is present but empty is a valid answer (member of no group) and userinfo is not asked. Only if the claim is missing in both places, the user counts as a member of no group. - byro looks for an existing account with the username from
username_field(defaultpreferred_username). If none is found, the user passes the group check from step 6 andauto_create_accountis enabled, it creates a new, passwordless account with the permissions described under OIDC groups and permissions. Ifauto_create_accountis disabled, sign-in fails for unknown usernames. - If
sync_groupsis enabled, the permissions of an existing, active account are updated from the groups and saved. - Group check: if
staff_groupis set, the user has to be a member ofstaff_groupor of the configuredsuperuser_group, or sign-in fails. This happens after step 5, so permissions that were just removed stay removed although the sign-in is rejected. - If the account has
is_active=False, sign-in is rejected with an error message. A deactivated account is never changed by step 5. - If the account is neither staff nor superuser, sign-in is rejected with an error message and recorded in the audit log.
OIDC groups and permissions¶
Two options map groups of the identity provider to the two flags of the permission model:
staff_group: members getis_staff. It also limits who may sign in through OIDC at all (step 6). If it is empty, every user of the identity provider may sign in.superuser_group: members getis_superuser. If it is empty, OIDC never grants or removes superuser status.
The two flags stay independent: membership in superuser_group never sets
is_staff by itself. Whether a member of superuser_group is also staff is
decided by the staff side alone:
- If
staff_groupis configured,is_stafffollows that group. A user who is only insuperuser_groupthen getsis_superuserwithoutis_staff, as a new account or throughsync_groups, and can still sign in, because a superuser always has access. - If no
staff_groupis configured, a new account becomes staff by default (see the table below), also when it is insuperuser_group. For an existing accountis_staffis left as it is.
So an account with is_superuser but without is_staff only comes about
when the staff side says so: through a configured staff_group, or because
the flag is already set that way locally.
A new account (auto_create_account) gets its permissions once:
staff_group set |
superuser_group set |
is_staff |
is_superuser |
|---|---|---|---|
| no | no | yes | no |
| yes | no | yes (membership is required to sign in) | no |
| no | yes | yes | if member of superuser_group |
| yes | yes | if member of staff_group |
if member of superuser_group |
So the simplest setup, auto_create_account without any group, still makes
every new OIDC user a regular staff account and never a superuser.
For an existing account it depends on sync_groups:
sync_groups = false(default): an OIDC login never changes the flags. The group check decides whether the user may sign in through OIDC, the local flags decide what the account may do. Being added to a group later grants nothing: a superuser sets the flags under "Settings → Users".sync_groups = true: see the next section.
Group names with spaces only work if the provider sends the groups claim
as a list; a claim sent as one string is split at spaces. A claim in any
other form, for example a list that contains something other than group
names, makes the sign-in fail. byro then creates no account and changes no
permissions.
Synchronizing permissions on every login¶
With sync_groups = true the identity provider is the source of truth
for the configured groups. On every successful OIDC login of an existing
account:
- if
staff_groupis set,is_staffis set to "member ofstaff_group", - if
superuser_groupis set,is_superuseris set to "member ofsuperuser_group", - a flag whose group is not configured is left exactly as it is.
byro reads the account again under a lock right before it compares and writes, and only writes a flag that is mapped and actually differs. A flag whose group is not configured is therefore never written, even if somebody changes it in the Office at the same moment.
A change is saved before the group check and the permission model are
evaluated and is recorded in the audit log with the old and new flags. A
user who was removed from staff_group loses is_staff with the next OIDC
login; if the account is neither staff nor superuser afterwards, that login
is rejected.
Warning
- Removing users from a synchronized group at the identity provider removes their permission in byro, without any safeguard. This can remove every superuser that signs in through OIDC. Keep a local break-glass superuser with a password.
- Synchronization only happens during an OIDC login of that account. Until then nothing changes: sessions, password sign-in and API tokens of the account keep working. byro never changes accounts that do not sign in through OIDC.
staff_groupalone does not manage superusers. After the update to the permission model, every existing account is a superuser (see Existing installations). Such an account losesis_staffand its OIDC sign-in when it leavesstaff_group, but keepsis_superuser, and with it password sign-in and its API token, until you also setsuperuser_groupor remove the flag by hand.- If the provider stops sending the
groupsclaim, for example after a changed scope or mapper, every user counts as a member of no group and loses the synchronized permissions with the next login.
The deprecated admin_group¶
admin_group is the old name of staff_group and is still read. On its
own it behaves as before: only members may sign in through OIDC, and new
accounts become staff. Two things are new: together with superuser_group,
membership in either group is enough to sign in, and with sync_groups
it also controls is_staff like staff_group does.
Rename it to staff_group when convenient. If both options are set to
different values, byro does not guess which one is meant: the SSO button
disappears and OIDC logins are refused until the configuration is fixed.
Password sign-in keeps working. manage.py check reports the problem and
byroctl config check refuses to apply such a configuration.
Error cases (an expired code, an invalid state, rejection by the
provider, a network error talking to the provider) all end up as an error
message on the login page; there is no dedicated error page and no fallback
to password login within the same attempt.
Warning
"Disable password" (see below) only blocks password sign-in for that
account. If OIDC is configured and the username matches, the account can
still sign in through OIDC. To lock an account out completely, it must
be removed or disabled at the OIDC provider itself (leaving the
configured groups is enough for the OIDC sign-in), or is_active must be
false.
Managing user accounts¶
Superuser only. Under "Settings → Users" (settings/users/) you see
every account, create new ones and edit existing ones. Staff accounts cannot
open this area; they can only edit their own profile through the user menu
(see My account), and that form does not contain the
two permission fields. Each account has:
- Username, name, e-mail address,
- Backend access (staff) (
is_staff): allows the account to sign in to the Office and to use the REST API (see API). Preselected when you create an account; switch it off if the account should not have access (yet). - Superuser (
is_superuser): additionally grants access to the superuser-only functions (see Permission model). Not preselected.
No self-demotion: in your own profile only the superuser field is locked.
You cannot remove your own superuser status; another superuser has to do
that. Your own is_staff stays editable: you can switch it on or off
yourself, which changes nothing as long as you are a superuser.
Password when editing: the password field of the edit form is optional.
Leave it empty to keep the account's password exactly as it is - this also
applies to a disabled password, which stays disabled. If you enter a
password, it replaces the current one when you save; tell the affected person
the new password afterwards. A password is still required when you create an
account. To set a password without opening the edit form, use
changepassword (see
Management commands).
Disabling a password (settings/users/<pk>/disable-password) sets an
unusable password; the account can no longer sign in with a password
afterwards (see the OIDC warning above about the interaction). It cannot be
applied to your own account. To re-enable password sign-in, save the edit
form with a new password.
Revoking an API token (settings/users/<pk>/revoke-api-token): the page
of another account shows whether that account has an
API token, never the token itself. "Revoke
API token" deletes it. The token stops working immediately (the API answers
with 401) and no replacement is issued. Nothing else about the account
changes: password, OIDC sign-in, MFA, sessions and permissions stay as they
are. It cannot be applied to your own account; use your own API token page
for that.
Revoking is not an API lock. It invalidates the token issued so far, for
example because it may have leaked. The owner of the account gets a new
token the next time they open their API token page. To keep an account away
from the API, remove is_staff and is_superuser (see
Permission model).
Every revocation is recorded in the audit log, without the token. If only that entry cannot be written, the token stays revoked nevertheless: you see a warning instead of the confirmation, and the application log gets a line with the ids of the two accounts, never the token or an error message.
If the revocation itself fails, for example because the database cannot store it, you get an error page. The outcome is then not confirmed: usually nothing was changed, but if the database was cut off while it stored the change, the token may be gone nevertheless. Open the page of the account again to see whether it still has a token, and revoke again if it does. The log of such an error contains no token either.
There is no way to delete or deactivate an account (set
is_active=False) through the Office UI. "Disable password" only blocks
password sign-in, and "Revoke API token" only invalidates the token issued
so far. To take away the access of an account, remove both is_staff and
is_superuser.
There is no self-service password reset and no invitation workflow for new accounts; a superuser creates every account themselves with an initial password. If no superuser is left who could create a new account, only server access helps, see Account recovery.
MFA requirement¶
Whether multi-factor authentication is optional or required for every account is a global setting, not per account: see Choosing an MFA policy.
Sign-in behavior¶
- The session cookie is named
byro_session, the CSRF cookiebyro_csrftoken; both are Django's default sessions with no fixed expiry beyond the browser session ending (noSESSION_COOKIE_AGEset). - No login lockout: byro does not lock an account after wrong password attempts (neither temporarily nor permanently; that only applies to MFA codes, see MFA). External protection (reverse proxy, Fail2ban) is up to you.
- Failed password logins do not end up in the audit log - only successful logins, logins on a deactivated account, logins rejected because the account has no backend access, and logouts are logged (see Audit log). Ending the session of an account that lost its backend access is logged as a logout. Permissions changed by the OIDC group synchronization are logged with the old and new flags; the entry contains no claims or group names.
- API tokens: creating, regenerating and revoking an API token is logged with the affected account and the account that did it. The entries never contain a token.