Users
The Users page manages user accounts for accessing GEM. Each user has authentication credentials, role assignments, and notification preferences.
Open Users
Overview
User accounts control access to GEM's web interface, mobile apps, and API. Users can be assigned multiple roles, associated with specific sites, and configured with notification profiles.
Creating and editing accounts requires a session you opened with a username and password on a role marked Elevated. A PIN sign-in at a wall panel never carries that authority, even for a user whose role has it — the page will refuse to save. See PIN Authentication.
Viewing Users
The grid, titled User Management, lists accounts sorted by username with the following columns:
- ID - Unique user identifier
- Username - Login username
- Email - Email address for notifications
- SMS - Phone number for SMS notifications
- Roles - Assigned roles (displayed as comma-separated list)
- Enabled - Whether the account is active
Two kinds of row are deliberately kept out of this grid: the internal none account (ID 0) and any account issued as a visitor. Visitors are managed from the dedicated Visitors page.
Grid Actions
- Add - Create a new user account
- Edit - Modify an existing user
- Reload - Refresh the grid data
User rows cannot be deleted from this grid — disable the account instead (clear Enabled or set Revoked) so audit history is preserved.
On a server whose accounts are managed by the tenant's primary site, the grid shows a "Users are managed by the auth server" banner and drops the Add/Edit actions — create and edit accounts on the primary instead; they arrive here automatically. Password changes and resets are blocked on a managed server too (a password changed locally would be reverted by the next push) — change it on the primary or through the cloud portal. Visitors stay site-local and can still be issued and revoked here. See Account Sync.
Creating a User
To create a new user account:
- Click Add in the grid toolbar. The form header reads New User
- Configure the user properties (see sections below)
- Click Create User
Editing an existing account works the same way, except the header reads Edit User - username with an Active or Inactive badge beside it, and the save button reads Update User. Cancel returns to the grid without saving.
User Configuration
The user editor is organized into five sections, in this order: Basic Information, Security Settings, Credential Lifecycle, Permissions & Access, and Additional Settings.
Basic Information
First Name / Last Name
- Optional human-readable name fields
- Used in access logs, visitor host selectors, and printed visitor badges
- First Name is the canonical input; Last Name is optional
Photo
- Optional headshot for the user
- Click Upload to pick an image file (max 1 MB) or Take Photo to capture from the device webcam
- Stored on the user record and printed on visitor badges when this user is selected as a Host
- Click Remove to clear the existing photo
- When Facial Recognition is enabled, the photo is auto-embedded locally (YuNet + MobileFaceNet) and the resulting 512-D embedding is stored encrypted as the
facial_recognition_embeddingattribute. If no face is detected,facial_recognition_embedding_errorrecords the reason. Per-user opt-out is thefacial_recognition_enabledattribute (defaults totrueonce the system-wide toggle is on).
Username
- Internal identifier, lower-case letters, numbers and underscores only
- Used for login. It is reformatted to that convention when you leave the field, and a name that still doesn't qualify is refused with "Name must be lower case letters, numbers and underscores only"
- Examples:
john_smith,admin,installer_1 - Treat it as permanent. The field stays editable on an existing account and GEM will not stop you renaming one, but access-log entries record the username as it was at the time, so past activity keeps showing the old name and no longer matches the account you are looking at
- Email address for notifications
- Optional but recommended
- Required for self-service password reset — a user with no email on file cannot reset their own password
- Required for Two-Factor Auth — an account with the switch on and no email here cannot sign in at all
SMS Number
- Phone number for SMS notifications
- Optional
- Format: +1 555-123-4567 (include country code)
- Used with notification profiles
Security Settings
All four credentials in this section work the same way: the input is greyed out until you tick the checkbox above it. Leaving a box unticked leaves that credential untouched, so you can change a PIN without retyping a password. Existing values are never shown back to you — the fields are always blank when the editor opens.
Password
- Tick Change password, then type the new password
- Stored as a PBKDF2-HMAC-SHA512 hash with a per-account random salt. Never displayed or logged in plain text, and there is no way to read an existing one back
- No minimum length is enforced here. An eight-character minimum applies only when a user changes their own password from the account menu (which also requires the new password to differ from the old). Setting a password for someone else on this page has no such floor, so choose a strong one deliberately
- Recommended: mixed case, numbers, symbols
PIN
- Tick Change PIN, then type the new PIN
- Used for wall-panel sign-in, mobile app quick access, and keypad/reader entry on access-control hardware
- Stored encrypted
- GEM does not enforce a length or a digits-only rule on a PIN you type here. Keep it numeric anyway — a door keypad has no letters. Six digits is the length GEM itself generates for visitor PINs and for the built-in
uipanel account - PINs must be unique across all users, including disabled ones, and are checked against every other account's PIN, duress PIN and card number. A save that collides is refused with a message naming the field it collided with, so keypad entry always resolves to a single person
Duress PIN
- Tick Change duress PIN to set a per-user silent panic code. The field hint reads "Grants access AND fires the rule's duress macro silently."
- Granting access uses the user's regular PIN; entering the duress PIN also grants access but additionally fires the access rule's Duress Macro (e.g. arm panic alarm, push notification to security)
- The attacker sees normal door behavior — there is no UI feedback that distinguishes the duress code
- A duress PIN is checked against every other account's PIN, card number and duress PIN — and against the same user's own PIN — so a duress code can never be swallowed by a normal one
RFID Card / Fob
- Tick Change card to enroll a card or fob number
- Enter the card UID exactly as the reader reports it, then use an Access Activity report to verify that presentations are recorded for the user
- Access rules with type RFID match the presented card against this value (2N and Brivo readers emit card reads today)
- Stored encrypted, and uniqueness-checked against every other account's PIN, card number and duress PIN
Credential Lifecycle
The first row of this section governs when the credentials above are honoured; the second row governs how long a session lasts and whether a second factor is required.
- Valid From — credentials grant access only at or after this time (optional)
- Valid Until — after this time, access is denied at the door and the user is auto-disabled on every linked access device on the next 15-minute sweep, so cached PINs on devices like 2N intercoms are also revoked
- Revoked — hard stop; overrides any valid window. Re-enabling (clearing this checkbox) automatically re-syncs credentials to all access devices the user has rights on.
Use these for contractor/visitor access without having to remember to manually disable the user when their term ends.
The window is enforced on every credential path, not just at the door: a revoked or out-of-window user is refused when signing in with a password or a PIN, and an already-open browser or app session is dropped at its next reconnect rather than surviving until it happens to expire. Revoking a dismissed contractor therefore ends their access now, not whenever their session times out.
Two-Factor Auth
- Switch, hinted "Require a one-time code on each login in addition to the password."
- Applies to every username + password login — the admin console, the end-user web UI, the mobile app, and the REST API
- The first sign-in attempt emails a 6-character code to the address on the account, and the login screen shows a Verification Code field. Enter the code to finish signing in
- The code is single-use and expires after 5 minutes by default. Requesting it again (submitting the login form again) issues a fresh one and invalidates the old. The expiry is recorded on the account rather than held in memory, so restarting GEM does not hand a mailed code an unlimited life
- A role can waive the code for sign-ins from the local network — see Skip 2FA on Local Network in Roles. That only ever skips a code; it can never impose one on an account whose switch here is off, and it never applies to a sign-in arriving through the cloud connector
- Codes use uppercase A–Z and 2–9 only, with visually ambiguous characters (
0/O,1/I/L) removed, so a code read off a phone is hard to retype wrong. The comparison is case-insensitive - An email address is required. With 2FA on and no email on the account, there is nowhere to send the challenge and the login is refused — set the email before enabling
- PIN logins are never challenged. A wall keypad has no inbox, so a PIN sign-in is unaffected by this switch (see PIN Authentication)
The second factor is emailed. SMS and authenticator apps are not used, even on a user who has an SMS number configured for notifications.
Session Timeout
- How long a session may sit idle, in minutes, before the user must sign in again
- The window is sliding: every request the user makes moves it forward, so someone actively using GEM is not signed out mid-use — only an idle session expires. The slide is persisted (within a few minutes), so it survives reconnects, network changes, and server restarts; an already-expired session cannot revive itself this way, since its requests are refused before they would slide anything
- 0 means the session never expires. New accounts default to 43200 (30 days), and leaving the field blank saves that default rather than 0
- Recommended: 60–480 minutes (1–8 hours) for accounts people sign into from phones, tablets and laptops — a session secret copied off one of those devices keeps working until that session has sat idle for this long
- 0 is the right setting for the built-in
uiaccount that drives in-wall touchscreens, which should never stop working and demand a PIN
Accounts created before this release defaulted to 0, so any account made without touching this field had a session that never expired. Updating sets those to 43200 (30 days) and names every changed account in the update log. The built-in ui wall-panel account is deliberately left untouched — on a site provisioned before the seed changed it stays at 0, which is what that hardware is meant to have.
If some other account drives an in-wall panel, set it back to 0 now — otherwise that panel starts asking for a PIN 30 days after the update, long after anyone would connect it to the upgrade. See Updates.
Permissions & Access
Roles
A scrolling checkbox grid of every enabled role, hinted "Roles determine which admin functions and device controls the user can access." Tick all that apply.
- Roles are what actually decide what a user can reach — which UIs, which routes, which functions
- Multiple roles combine additively: the user gets the union of every ticked role's rules. Elevated follows the same most-permissive-wins rule, so one Elevated role makes the user Elevated
- Allow Remote and Skip 2FA on Local Network go the other way — every role the user holds must permit them. One local-only role keeps the whole account on site, and one role without the 2FA waiver means the code is always required
- Changes take effect on the user's next sign-in
A fresh install seeds exactly two roles, and you build the rest yourself:
admin— full access (allow ui *,allow route *,allow api *) and Elevated. This is the role on the administrator account created during installationui— the wall-panel operator role: everything except the admin console (deny route /admin*), not Elevated
There is no seeded user, installer, viewer or api_only role. If you want those, create them on the Roles page first — they will not appear in this grid until they exist.
Sites
A checkbox grid of site names, hinted "Restrict the user to specific sites. Leave empty for access to all sites." What this list actually does depends on how the account signs in, and the two behave differently:
- Browser, mobile app and wall panel sign-in — the list is recorded on the account and reported back at sign-in, but access is decided by roles. Leaving it empty does not lock anyone out
- REST API sign-in — the list is enforced. Requesting a token requires the account to name at least one enabled site, and to hold at least one role
This is the opposite of what the on-screen hint suggests. An account with an empty Sites list is refused at POST /api/token with unauthorized and the message "no sites found" — the password and any 2FA code are correct and it still fails. An account with sites but no roles is refused the same way with "invalid roles".
If an integration is failing to authenticate and the credentials are definitely right, tick the site (and confirm that site is enabled on the Sites page) before looking anywhere else.
Additional Settings
Notification Profile
- Picks the profile that decides when and how this user receives notifications — email, SMS and web-push channel toggles, active days, and active hours
- Click New beside the picker to build a profile without leaving the user form; the new profile is selected automatically when you save it
- See Notification Profiles for details
Account Status
- Switch, reading Enabled or Disabled beside it
- Disabled users cannot log in, and are dropped from the live session cache immediately
- Preserves all configuration and history
Personal Settings
Appears when you edit an existing account. These are UI settings overridden for this one person — wallpaper, theme, the page they land on, their weather location — and they follow the account onto every screen they sign in to.
- A blank field means the user inherits whatever the UI uses; Reset removes an override
- Fields save as soon as they change. They are attribute rows on the account rather than part of the user record, so they do not wait for Update User
- Users can change these themselves under Tools → My Settings
- Only settings marked user-overridable appear here. Permission-bearing settings — protected routes, roam restrictions, backup configuration — are deliberately excluded and cannot be personalized
- See Personal Settings for the full resolution order and how to add a new personalizable setting
User Status
User accounts can be in different states:
Active
- Account Status = Enabled
- Can log in and access permitted resources
- Shown as a green Active badge beside the username in the editor header
Inactive
- Account Status = Disabled
- Cannot log in
- Configuration preserved
- Shown as a red Inactive badge beside the username in the editor header
Throttled
- Not an account state — a temporary block on the origin of the failed attempts
- See Failed login throttling below
Failed login throttling
Repeated failed credentials are rate-limited automatically. No configuration, and nothing to unlock by hand.
- The first 5 failures from an origin are free. Every failure after that starts a lockout that doubles each time — 5 seconds, then 10, 20, and so on, capped at 15 minutes.
- Counters are keyed on the connection's peer address, so one person fumbling their PIN at the back door can never lock out anyone signing in from elsewhere. A second, narrower counter is also kept per client on that address, so a single misbehaving panel trips its own lockout first.
- The address is the part that decides the block, and it is taken from the connection itself rather than from anything the client sends. A client that reconnects under a new identity each attempt keeps counting against the same address bucket.
- PIN and password attempts are counted separately, even from the same address and the same client. Signing in with a username and password therefore has no effect on the PIN counter at that address, and vice versa — holding one ordinary account does not buy fresh PIN guesses.
- A successful login clears the counter for that credential type only. Someone who mistypes their PIN twice and gets it right on the third try starts clean, so a shared wall panel never goes dark on its occupants.
- Counters decay after 15 minutes of quiet, and are held in memory only: restarting the server clears them.
- While blocked, the attempt is refused with "too many attempts, try again later" before any credential is checked.
This matters most for PIN logins. A PIN carries no username, so every attempt has to scan the user list and decrypt each stored PIN to find a match — which made a short PIN space guessable, and made repeated attempts expensive for a live controller. The throttle now fires before that work happens.
Within the password path both failures count the same: an unknown username and a valid-username-wrong-password both increment the same counter, so alternating between them doesn't reset it.
Session binding
A session is identified by its client_id and authenticated by a bearer secret the server issues at login. The browser or panel stores that secret and presents it on every socket connection.
client_idalone is no longer sufficient to adopt a session. It travels in the connection query string and a non-HttpOnly cookie, so it appears in proxy and tunnel logs — knowing one must not be the same as being signed in.- Signing out rotates the stored secret, so a captured value is dead the moment the user logs out.
- Requesting a fresh resource token no longer extends an expired session. An expired panel session must log in again rather than being renewable indefinitely.
- The admin console and the end-user UI are separate sessions, each with its own stored secret, even in the same browser. Signing into one no longer overwrites the other's secret, so an admin tab and a user tab in the same browser no longer bounce each other to the login screen on their next page load.
Sessions created before this change carry no bearer secret, so every browser and wall panel is signed out once on the first connection after the update. Have panel PINs to hand before updating a site. See Updates.
Signing in through the cloud proxy
When a site is reached remotely through the GEM cloud proxy, the proxy is the front door: it collects the username, password and 2FA code and verifies them against this controller. Once that succeeds the browser is signed into GEM directly — the user is not asked for the same credentials a second time, and a 2FA user is not emailed a second code (the first is consumed on use).
What this does and does not change:
- Nothing is trusted because it arrived through the tunnel. The handoff is authorized by the API token the proxy earned by passing the full credential and 2FA check here; a request header claiming to be tunnel traffic grants nothing.
- The handoff is single-use and short-lived, and is re-checked when it is redeemed — the account must still exist, still be inside its validity window, and hold no role with Allow Remote off. A local-only account is refused here rather than being handed a session that fails on every subsequent request. See Roles.
- The resulting session is an ordinary password session, with the same admin authority the user would have signing in locally, and the same Session Timeout as any other.
- A browser that already holds a valid session keeps it — the handoff is only used when there is no session to resume, so reconnecting does not consume one.
Security Best Practices
Password Management
- Strong Passwords: GEM does not enforce complexity or a minimum length when an admin sets a password here, so the strength of an account is entirely your choice at the moment you type it
- No Sharing: each person gets their own account — a shared login makes the access log useless
- Service Accounts: use a dedicated account per integration, so you can revoke one without disturbing the others
- Hand off rotation: after you set someone's password, tell them to change it themselves from the account menu — resetting it here does not prompt them to
Role Assignment
- Least Privilege: build a role with the rights the job needs rather than reaching for
admin - Role Segregation: keep the commissioning role separate from the day-to-day one, so you can retire it at handover
- Review Regularly: audit role assignments periodically — roles are additive, so extras only ever widen access
- Retire Unused: accounts cannot be deleted. Disable them, or tick Revoke credentials
Two-Factor Authentication
- Enable for Admins: always require 2FA on accounts that hold an Elevated role
- Confirm the email first: turning the switch on for an account with no email address locks that account out entirely
- Remote Access: a role can waive the code on the local network while still requiring it through the cloud connector — see Skip 2FA on Local Network in Roles
Session Management
- Appropriate Timeouts: balance security and convenience
- Admin accounts: 60–120 minutes
- Everyday accounts on phones and tablets: 240–480 minutes
- In-wall panels: 0 (never expires) is the intended setting for the
uiaccount, and only for hardware physically inside the building
- Sign out to end a session now: signing out immediately invalidates that client's session; it does not wait for the timeout
- Revoke rather than wait: to end a person's access immediately across every device, tick Revoke credentials — open sessions are dropped at their next reconnect
Monitoring
- Login Tracking: Review access logs regularly
- Failed Attempts: Monitor for brute force attacks — repeated failures are throttled automatically (see Failed login throttling), but a sustained pattern is still worth investigating
- Unusual Activity: Investigate unexpected access patterns
- Audit Changes: Track who modified what configuration
Common Workflows
Creating an Admin User
- Click Add
- Username:
admin_firstname - Email: a mailbox the person actually reads — 2FA and password resets both go there
- Tick Change password and set a strong password
- Under Permissions & Access, tick the
adminrole - Turn Two-Factor Auth on
- Session Timeout: 120 minutes
- Click Create User
Creating a Standard User
- Click Add
- Username:
homeowner_name - Email: for notifications and password reset
- Tick Change password and set a password
- Tick the role that covers day-to-day use. On a fresh system that is
ui; on a system where you have built your own, tick that one - Notification Profile: pick one, or click New to build it here
- Click Create User
Creating an Installer Account
- Click Add
- Username:
installer_company - Tick Change password and set a temporary password
- Tick the commissioning role —
adminif you want full access, otherwise a role you built with the specific rights the job needs - Session Timeout: 480 minutes (8 hours)
- Under Credential Lifecycle, set Valid Until to the end of the engagement. This beats relying on someone remembering to come back and switch the account off
- Account Status: Enabled
- Click Create User, then provide the credentials to the installer
Creating an API Service Account
- Click Add
- Username:
api_integration_name - Tick Change password and set a strong random password
- Tick a role that grants the functions the integration calls. There is no seeded API-only role — build one on the Roles page if you want the integration confined
- Under Sites, tick at least one enabled site. A token request from an account with no site is refused outright — see the warning under Sites
- Leave Session Timeout at the default. REST API tokens have their own lifetime (default 1 hour) and are not governed by this field. Do not set 0 here just to make an integration convenient; 0 means a UI session for this account would never expire
- Leave Notification Profile empty
- Click Create User, then use the credentials in the integration
Resetting a Password
- Edit the user
- Tick Change password
- Enter the new password
- Click Update User
- Notify the user of the password change
Self-Service Password Reset
A user who can't sign in can request a reset from the login screen. GEM emails them a one-time link:
- The user types their username on the login screen and clicks Reset Password, then confirms.
- The screen shows "Please check your email" and GEM mails a
/reset_password?token=…link to the address on the account. - Opening the link sets a new password and mails it to the same address.
The mechanics matter for troubleshooting:
- Tokens are single-use and expire after 30 minutes. Following the same link twice fails the second time. Reset state is held in memory, so restarting GEM invalidates any link that hasn't been used yet — the user just requests another.
- The link is built from the server's configured
external_url, never from the browser that asked for the reset. Ifexternal_urlis unset the request origin is used as a fallback and a warning is logged, so set it under Installation on any install that uses self-service reset. - The response is always the same, whether or not the username exists and whether or not it has an email address. This stops the form from being used to enumerate valid accounts — so "I requested a reset and nothing arrived" usually means a typo'd username, a missing email on the account, or mail delivery.
- Repeat requests for the same username are throttled to one email per minute. The user still sees a success message; no second email is sent.
- Reset tokens are entirely separate from session tokens — a reset request never touches the requesting client's session, and never signs anyone in.
Self-service reset is unavailable on a server whose accounts are managed by the tenant's primary site — reset the password on the primary or through the cloud portal instead. See Account Sync.
Disabling a User Account
- Edit the user
- Under Additional Settings, switch Account Status to Disabled
- Click Update User
- The user immediately loses access — existing browser and panel sessions are dropped at their next reconnect, not whenever they would have expired
Granting Temporary Access
Let the account expire itself rather than putting a reminder in a calendar:
- Create the user with the roles the job needs
- Under Credential Lifecycle, set Valid From (optional) and Valid Until to the end of the term
- Account Status: Enabled
- Click Create User
When Valid Until passes, the account stops working on every path — door, panel, browser, app and API — and GEM also disables the user on each linked access device within about fifteen minutes, so a PIN cached on an intercom stops working too. To end access sooner, edit the user and tick Revoke credentials.
User Account Limitations
Username Restrictions
- Cannot change username after creation
- Username must be unique
- Lower-case letters, numbers and underscores only — no spaces, no other punctuation
- Reformatted automatically when you leave the field; a name that still doesn't qualify is refused on save
- Renaming an existing account is not blocked, but past access-log entries keep the name recorded at the time, so treat the username as permanent
Deletion Restrictions
- The Users grid does not expose a delete action — disable the account instead (switch Account Status to Disabled, or tick Revoke credentials) so audit history stays intact
- The internal
noneaccount (ID 0) is a system placeholder and is hidden from the grid entirely - Visitors expire on their own Valid Until window — see Visitors
System Accounts
- User ID 0 is the internal
noneaccount — the placeholder GEM records against activity that no person initiated, such as a schedule firing a macro overnight - It is permanently disabled and has no credentials, so nothing can sign in as it. GEM re-asserts that at every boot, so re-enabling or renaming it by hand does not stick
- It is hidden from the Users grid, and there is nothing to configure on it
Authentication Methods
Password Authentication
- Default method for the web interface, mobile app and API
- Stored as a PBKDF2-HMAC-SHA512 hash with a per-account random salt — the plaintext is never written down and cannot be read back out of GEM
- The only ways to change one are an admin setting it on this page, the user changing their own from the account menu, or self-service reset
Forced password change. When GEM creates the administrator account during installation without being given a password, it seeds a fallback one and flags the account to change it at first sign-in. The user is prompted on their next sign-in and the flag clears once they set a new password. There is no checkbox for this on the Users page — an admin resetting someone's password here does not force a change, so tell the user to rotate it themselves.
PIN Authentication
- Used for wall-panel and mobile app quick access, and at keypad/reader hardware
- Signing in by PIN needs no username: the server matches the PIN against every active user
- Numeric in practice — generated visitor PINs are 4–8 digits (6 by default), and the seeded
uipanel account gets a random 6-digit one - Never carries admin authority, whatever the user's role. A PIN session reaches its UIs and controls — including devices and macros flagged Elevated, which the PIN already opens at the keypad — but admin-only functions, secure attribute values, generic writes, backups and the
/adminconsole are refused. Sign in with a username and password for admin work. See Roles → Elevated - One deliberate exception: a role that grants an admin-only function by name rather than by wildcard still works on a PIN session. That is how a kiosk role is given one narrow privileged action without handing the panel the admin console. A blanket
allow api *does not qualify — it has to be the named function - Weaker than a password by construction: a short numeric code, entered in public, often shared. Give each person their own rather than sharing one, and set Valid Until on temporary ones
ui account's PIN if GEM warns about itEarly builds seeded the built-in ui wall-panel account with a PIN written as a literal in GEM's source, which makes it public in the release history. New installs generate a random PIN instead, but a controller provisioned before that change kept the shipped one — provisioning is a first-boot step and never re-runs.
GEM checks this on every boot and logs a warning naming the account if it is still in use. The ui role holds allow api *, so that PIN can unlock doors, open gates and disarm security from any panel that reaches a login screen; if the account also has Session Timeout 0, a login obtained with it never ends.
It is a warning rather than an automatic rotation on purpose — wall panels, keypads and household members use this PIN daily, so changing it silently during an upgrade would lock a site out of its own building. Rotate it deliberately: edit the ui user, tick Change PIN, set a new one, click Update User, then re-enter it on every wall panel.
Token Authentication
GEM issues two different things called a token, and they expire on different clocks:
- A UI session, minted when someone signs into the web UI, the app or a panel. It lasts as long as that account's Session Timeout, and signing out ends it immediately
- A REST API token, minted by the API's token request. It has its own lifetime — one hour by default — and is not governed by Session Timeout at all
Both are invalidated by signing out. See REST API for the API side.
Two-Factor Authentication
When enabled on a user, every username + password login is challenged — the admin console, the end-user web UI, the mobile app and the REST API all use the same gate:
- User enters username and password
- GEM emails a 6-character code to the address on the account and answers with a challenge instead of a session — no session exists at this point
- The login screen shows a Verification Code field; the user enters the code
- The code is checked case-insensitively, cleared on use, and the session is created
Codes expire after 5 minutes and are single-use. A wrong or expired code re-prompts on the same field; repeated failures are rate-limited by failed login throttling like any other credential. Submitting the login form again issues a fresh code.
PIN logins are not challenged — see PIN Authentication.
Permissions and Access Control
Four things decide whether a request succeeds, checked in this order:
- Account Status — a disabled account cannot sign in, and is dropped from the live session cache
- Credential Lifecycle — Revoked, or a time outside Valid From / Valid Until, is refused on every path: door, panel, browser, app and API
- How the credential was proved — a PIN sign-in never carries admin authority, even on an Elevated role
- Roles — the union of every role's rules decides which UIs, routes and functions are reachable
Sites is not in that list for browser, app and panel sign-in — it is recorded and reported, not enforced. It is enforced for REST API token requests, which additionally require at least one role.
See Roles for detailed permission configuration.
Troubleshooting
User Cannot Log In
Check:
- Account Status: the account must be Enabled
- Credential Lifecycle: Revoked ticked, or a Valid Until in the past, refuses the sign-in with the same generic "Invalid credentials" a wrong password gives. The login screen deliberately will not tell the user which it was — check the account
- Password: verify it is correct, and that you are not on a server whose accounts come from the primary site (see Account Sync)
- Throttling: after repeated failures the attempt is refused with "too many attempts, try again later" before the password is even checked. Wait it out — see Failed login throttling
- Two-Factor Auth on with no email: the account cannot sign in at all until an email address is set
- Allow Remote: if the user is off-site, a role that is local-only refuses the connection. Check the role, not the account
- REST API only: no site ticked, or no role ticked — see the warning under Sites
User Has Wrong Permissions
Check:
- Roles: verify the correct roles are ticked. Remember they combine additively — an unexpected extra role can only ever add access
- Role Rules: check the role's rules on the Roles page
- Signed in with a PIN: admin functions are withheld from PIN sessions regardless of role. Sign in with username and password instead
- Stale session: role changes take effect at the user's next sign-in — have them sign out and back in
Two-Factor Not Working
Check:
- Email address: the code is emailed — a 2FA account with no email on file cannot sign in at all, and the login screen says so ("Two-factor authentication is enabled on this account but it has no email address")
- Mail delivery: check the spam folder, and confirm outbound mail works from the controller
- Code expiry: codes expire after 5 minutes. Submit the login form again to get a fresh one — the old code stops working
- Wrong code: entering the code from an earlier email fails; only the most recent one is valid
- Throttling: repeated failures trigger failed login throttling on that client + IP
- Expecting an SMS or authenticator prompt: neither is used — email is the only channel
Session Expires Too Quickly
Solution:
- Edit the user
- Increase Session Timeout under Credential Lifecycle
- Click Update User
- The user must sign in again for the new timeout to apply
Removing a User
The Users grid does not have a delete action by design — deleting a user would orphan access logs, audit history, and access-control references. Instead:
- Edit the user
- Switch Account Status to Disabled, or tick Revoke credentials under Credential Lifecycle
- Click Update User
The account immediately loses access (revoked credentials propagate to access devices), but history and references stay intact.
Related Documentation
- Roles - Configuring user roles and permissions
- Account Sync - Pushing accounts from the primary site to peer servers
- Sites - Multi-site access control
- Access Control - Physical access control
- Notification Profiles - User notifications
- Personal Settings - Per-user wallpaper, theme and homepage overrides
- Access Activity - Investigating physical access events