Login security & two-factor
Configure account lockout, self-service password reset, magic links and two-factor authentication through the API, provision users without handling passwords, and keep integration accounts clear of sign-in interstitials.
Yurbi includes a set of login-security features: account lockout after failed
attempts, self-service password reset and one-time sign-in links, two-factor
authentication (authenticator app, email code, text message or Duo), administrator
disable, forced password change, and an EXTERNAL authentication method for
accounts owned by an upstream identity provider.
Everything is off by default. An upgraded instance behaves exactly as before until an administrator turns a feature on, and every new field on the user and settings objects is optional — requests that omit them leave the account or setting unchanged. Existing integrations do not need to change.
This guide covers what an integrator needs: the settings keys, the user-state fields, the endpoints for provisioning and help-desk actions, and how to keep accounts your application signs in on behalf of users out of the two-factor and password-change screens.
1. Instance settings
All of these live in the settings object returned by
GetAppSettings and written by
SaveAppSettings. Boolean values are the strings
"True" and "False". In the interface they are under Settings → Server
Settings → Security Settings.
| Key | Default | Meaning |
|---|---|---|
enableloginlockout |
False |
5 failed password attempts lock the account for 5 minutes. Password sign-ins only; SSO, Windows, EXTERNAL and magic-link sign-ins are never counted. The counter is per server and clears on restart. |
allowpasswordreset |
False |
Shows Forgot password? on the sign-in page. Links expire in 15 minutes and work once. |
allowmagiclink |
False |
Shows Email me a sign-in link. Same 15-minute, single-use link; two-factor still applies after it. |
publicbaseurl |
empty | The address users reach Yurbi at, e.g. https://reports.example.com or https://example.com/yurbi under a sub-folder. Every emailed link is built from it. Required before either recovery switch, or AdminSendLink, will work. |
invite_subject, invite_message |
see below | Subject and intro text of the welcome email sent by AdminSendLink (kind: invite). Placeholders {product}, {username}, {firstname}. |
twofa_mode |
off |
off, optional (users may enroll; enrolled users are challenged) or required (every password user must enroll before reaching the application). |
twofa_methods |
duo,totp,email,sms |
Comma list of methods users may enroll. email needs SMTP; sms needs a text-message provider configured in the interface; duo needs the existing duo_* keys. |
enforcestrongpassword |
False |
Existing key: minimum length and breach screening for new passwords, applied to the reset page as well. |
SaveAppSettings replaces the whole object, so read first and send back what you
received. Two rules the interface enforces and the API does not check for you: a
twofa_mode other than off needs at least one method in twofa_methods, and
publicbaseurl must be set before allowpasswordreset or allowmagiclink is turned
on.
curl -X POST "https://your-yurbi-server.com/api/AppSettings/SaveAppSettings" \
-H "Content-Type: application/json" \
-d '{
"sessionToken": "YOUR_SESSION_TOKEN",
"appsettings": {
"...": "every key returned by GetAppSettings, unchanged, plus:",
"publicbaseurl": "https://reports.example.com",
"allowpasswordreset": "True",
"enableloginlockout": "True",
"twofa_mode": "optional",
"twofa_methods": "totp,email"
}
}'
A sensible rollout: set publicbaseurl and confirm email works → turn on
allowpasswordreset → set twofa_mode to optional and let administrators
enroll → switch to required.
2. User account fields
The user object used by SaveContact,
GetContactById and the other Users endpoints
carries the account's security state. All are optional on save.
| Field | Values | Notes |
|---|---|---|
AuthType |
PIN, SSO, Windows, EXTERNAL |
PIN is a password user. EXTERNAL marks an account authenticated entirely upstream; it holds no password and cannot use password reset, magic links or invite links. |
disabled |
true / false |
Blocks every sign-in method and ends the current session. Set it directly, or use DisableContact / EnableContact. |
bforcepasschange |
true / false |
The user must set a new password at their next password sign-in. Clears itself when they do. Ignored for SSO, Windows and EXTERNAL users. |
lockdate |
timestamp | Read-only. When lockout is on and the account is locked, the time the lock expires; otherwise 0001-01-01T00:00:00. Clear it early with UnlockContact. |
twofa |
none, setup_required, duo |
setup_required asks the user to enroll at their next sign-in (they may skip in Optional mode). duo assigns Duo. Authenticator, email and SMS are self-enrolled and are not removed by saving none. |
3. Provisioning users without handling passwords
The usual flow sends a generated password to the user out of band. The alternative is an invite link: the user sets their own password from a welcome email, and your system never knows it.
- Create the user with
SaveContactas normal, using a long randomPinthe user will never see. - Call
AdminSendLinkwithkind: "invite".
curl -X POST "https://your-yurbi-server.com/api/Recovery/AdminSendLink" \
-H "Content-Type: application/json" \
-d '{ "sessionToken": "YOUR_SESSION_TOKEN", "loginName": "jsmith", "kind": "invite" }'
The user receives the welcome email with a Set your password link valid for 72
hours. If two-factor is required, they enroll immediately after. The same call
with kind: "reset" sends a standard 1-hour reset link and is the right action for
a help-desk "forgot my password" ticket — it works even when self-service reset is
off. Requirements: the user is AuthType PIN with an email address, SMTP is
configured, and publicbaseurl is set.
4. Help-desk and lifecycle actions
| Situation | Call |
|---|---|
| Person leaves or is suspended | DisableContact — ends their session now, keeps their content. Reverse with EnableContact. |
| Locked out after failed attempts | UnlockContact (only relevant when enableloginlockout is on). |
| Forgot password | AdminSendLink with kind: "reset". |
| Suspected shared or leaked password | SaveContact with bforcepasschange: true, or send a reset link. |
| Lost phone / new authenticator | TwoFactor/AdminStatus to see what is enrolled, then TwoFactor/AdminReset to clear it. The user re-enrolls at next sign-in if two-factor is required. |
| Password-age policy, or a breach | ForcePasswordResetAll with olderThanDays — every matching password user must change at next sign-in. |
All of these require an administrator session (ErrorCode 9000 /
PERMISSION_DENIED otherwise) and are written to the Audit Log.
5. Integrations that sign users in: avoiding interstitials
When your application calls DoLogin on a user's behalf —
for session-token SSO or
embedding — the user never sees Yurbi's sign-in page, so they
cannot answer a two-factor prompt or set a new password there. In those states
DoLogin still returns ErrorCode 0 and a token, but the session is pending
and every other call with it is refused:
| Response field | Meaning |
|---|---|
requiresTwoFactor: true, twoFactorMethod |
The user has a two-factor method enrolled and must enter a code in Yurbi. |
requiresTwoFactorEnrollment: true |
twofa_mode is required and the user has not enrolled. |
LoginUser.bforcepasschange: true |
A new password must be set before the token is useful. |
Keep accounts your application signs in out of these states:
- Two-factor. Either leave
twofa_modeatofforoptionaland do not enroll those accounts, or — if your interactive users needrequired— give the accounts your application controls theEXTERNALauthentication method and sign them in through header-based SSO, which is exempt from Yurbi's two-factor. Per-user enforcement of two-factor is planned; today the mode is instance-wide for password users. - Forced password change. Do not set
bforcepasschangeon accounts your application owns the credentials for; rotate thePinwithSaveContactinstead. - Lockout. A wrong cached password will lock the account after 5 attempts when
enableloginlockoutis on, andDoLoginthen returnsErrorCode 101for 5 minutes. Fix the stored credential before retrying.
Check for the three fields after every DoLogin and treat any of them as "token
not ready" rather than retrying.
6. The EXTERNAL authentication method
EXTERNAL is for accounts that are always authenticated by another system and
should never hold a Yurbi password — today an identity provider sending the
SSO header; SAML and OIDC are planned. Compared with SSO,
it is explicit about the contract:
- No password is stored or accepted. Password sign-in, password reset, magic links and invite links all refuse the account.
- Header-based SSO signs the account in exactly as for
SSO. - Lockout, forced password change and Yurbi's two-factor prompts do not apply; those controls belong to the identity provider.
- Saving a user as
EXTERNALclears any pending forced password change. ExistingSSOusers are unchanged.
7. Audit events
Every action above is recorded and visible through
GetAuditTypes and the Audit Log in the interface.
Type numbers (the type field; the table ID is one higher):
| Type | Event |
|---|---|
| 20 / 21 | Password reset requested / completed (includes admin-sent and invite links) |
| 22 / 23 | Magic link requested / used to sign in |
| 24 / 25 | User disabled / enabled |
| 26 / 27 | Account locked / unlocked |
| 28 / 29 | Two-factor enrolled / removed by the user |
| 30 / 31 / 32 | Two-factor challenge issued / code accepted / code rejected |
| 33 | Two-factor reset by an administrator |
| 34 / 35 | Backup codes generated / used |
| 36 / 37 | Trusted device remembered / revoked |
| 38 | Forced password reset for all users |
Endpoints used
GetAppSettings/SaveAppSettings— security settingsSaveContact—AuthType,disabled,bforcepasschange,twofaAdminSendLink— invite and reset linksDisableContact/EnableContact/UnlockContactTwoFactor/AdminStatus/TwoFactor/AdminResetForcePasswordResetAllGetAuditTypes