Contact us
Guides

Login security & two-factor

Configure account lockout, password rules, self-service password reset, magic links and two-factor authentication through the API, provision users without handling passwords, and keep integration accounts working with service accounts.

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.
service_account true / false The account belongs to an integration, not a person: it is never asked for a second factor or a forced password change. Set it directly or with SetServiceAccount. See section 5.

Password rules. Any Pin you send is trimmed of leading and trailing spaces, and a blank one is rejected. When enforcestrongpassword is on, a new password must be 12–128 characters, must not contain the login name, and must not be a common or publicly breached password; SaveContact returns the reason in ErrorMessage when one fails. Generate 32+ random characters for integration accounts and you will never hit a rule. For EXTERNAL users send withpin: false and no Pin.

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.

  1. Create the user with SaveContact as normal, using a long random Pin the user will never see.
  2. Call AdminSendLink with kind: "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. Service accounts are skipped.
New integration, embed host or Server Sync user SetServiceAccount with enabled: true before two-factor is turned on.

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: service accounts

When your application calls DoLogin on an account's behalf — for session-token SSO, embedding, a scheduled export or Server Sync — nobody is there to type a two-factor code or choose a new password. If the instance turns on two-factor or forces a password change, DoLogin still returns ErrorCode 0 and a token, but the session is pending:

Response field Meaning
requiresTwoFactor: true, twoFactorMethod The account has a two-factor method enrolled and must enter a code in Yurbi.
requiresTwoFactorEnrollment: true twofa_mode is required and the account has not enrolled.
LoginUser.bforcepasschange: true A new password must be set before the token is useful.

Every other call made with a pending token returns ErrorCode 9000 with ErrorMessage TWO_FACTOR_PENDING.

The fix is to flag the account as a service account:

curl -X POST "https://your-yurbi-server.com/api/Contact/SetServiceAccount" \
  -H "Content-Type: application/json" \
  -d '{ "sessionToken": "YOUR_SESSION_TOKEN", "loginName": "svc-reporting", "enabled": true }'

A service account is never asked for a second factor or a forced password change, whatever the instance's two-factor mode, so DoLogin always returns a usable token. Do this for every account your integration signs in with, before the instance's administrators turn on two-factor. It also covers the user Server Sync signs in with on each destination server. The flag is visible in the Yurbi user editor as Service account (API integration), and every sign-in where the second factor was skipped is written to the Audit Log.

What a service account does not skip:

  • Lockout. Five wrong passwords still lock it for 5 minutes (ErrorCode 101 from DoLogin). A stale stored password is the usual cause; fix the credential before retrying, and rotate passwords on your own schedule with SaveContact rather than through a forced change.
  • Password rules when its password is set, and the disabled flag.

Rules: an administrator cannot flag their own account, and the built-in admin account can only be flagged while signed in as admin — give integrations their own accounts rather than using admin. Give each integration its own account: Yurbi keeps one session per user, so two systems sharing an account sign each other out.

Embedding end users who need two-factor. The embed flow signs in as the end user's own account, so a person who is required to use two-factor cannot be embedded as themselves. Embed with a service account that has the content access those users need, or sign them in through SSO or the EXTERNAL method instead.

Check for the three response 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 EXTERNAL clears any pending forced password change. Existing SSO users 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
50 / 51 Service account flag set / cleared
52 Two-factor skipped (a service account signed in)
53 Password changed (by the user, a forced change, or an administrator)

Endpoints used