Password policy and access protection

Security mechanisms

1. Protection against password mining

Two independent layers — short-term lockout on a series of failures in process memory and permanent account lockout — deny login after a configurable number of failed attempts. The invalid password, the temporary series lockout, and the permanent lockout return a 401 error so that an attacker cannot distinguish between them.

Failures are additionally accompanied by a random delay so that a lockout cannot be distinguished from a slow password check by response time.

Environment variables for configuring thresholds

Environment variable Default Description

TNGRI_LOGIN_THROTTLE_MAX_FAILURES

10

Number of failed login attempts from a single IP address before a ban is imposed.

TNGRI_LOGIN_THROTTLE_RAPID_WINDOW_S

60

Maximum interval (seconds) between failed login attempts for them to be considered part of a single series.

TNGRI_LOGIN_THROTTLE_BASE_BAN_S

60

Initial ban duration (doubles with each series).

TNGRI_LOGIN_THROTTLE_IDLE_RESET_S

3600

Idle time after which the failure counters are reset.

TNGRI_LOGIN_THROTTLE_JITTER_MIN_MS

250

Minimum artificial delay during a lockout.

TNGRI_LOGIN_THROTTLE_JITTER_MAX_MS

1500

Maximum artificial delay during a lockout.

2. Password policy

Each new password is checked against the following parameters:

  • Length

  • Character variety

  • Use of login fragments in the password

  • Use of previous passwords

A password has a lifetime — the period during which the password is valid. When it expires, the account is locked until unlocked by an administrator.

Default values are set conservatively and are configurable via environment variables.

Environment variables for configuring password policy

Environment variable Default Description

TNGRI_PASSWORD_POLICY_ENABLED

True

Enable password policy restrictions (if disabled, passwords can be anything).

TNGRI_PASSWORD_POLICY_MIN_LENGTH

12

Minimum password length.

TNGRI_PASSWORD_POLICY_REQUIRED_GROUPS

4

Required number of character groups (uppercase/lowercase letters, numbers, special characters).

TNGRI_PASSWORD_POLICY_MIN_LOGIN_FRAGMENT

3

Prohibit login fragments of this length or longer within the password.

TNGRI_PASSWORD_POLICY_HISTORY_SIZE

10

Number of previous passwords that cannot be reused.

TNGRI_PASSWORD_POLICY_MAX_AGE_DAYS

90

Password rotation period (in days).

TNGRI_PASSWORD_POLICY_MAX_FAILED_LOGINS

10

Number of failed login attempts before the account is locked.

TNGRI_PASSWORD_POLICY_REQUIRE_CURRENT_PASSWORD

False

Require the current password when a non-administrator changes their own password.

TNGRI_PASSWORD_POLICY_MIN_CHAR_DIFF

3

Minimum number of characters that must differ between the old and new passwords.

3. Recovery token

When an administrator account is locked out by an attacker’s attempts to find its password, the administrator can present a recovery token to the system to log in. This is done by executing a POST /auth/recovery request with their token. This action resets all locks and allows the administrator to log in to the system.

All three mechanisms apply to password login only (POST /auth/login, SCRAM-SHA-256 on top of psql). SSO login or token authentication do not use these mechanisms.

Recovery checklists

Configuring the recovery token

  1. Immediately after system installation, issue a recovery token for the default administrator account:

    prostore user mint-recovery --username admin
  2. Save the token in the command password manager outside the main system. The command shows the token once, and Tengri will not be able to show it again.

  3. Repeat these steps for each account that needs a recovery method. There is no system-wide master recovery token — tokens are issued one per user.

During an incident

  1. From the log, identify the blocked account:
    account '<user>' blocked after N failed login attempts

  2. From a trusted client, send the saved token to the recovery logon point along with the name of the blocked account:

    curl -X POST https://<host>/auth/recovery \
      -H 'Content-Type: application/json' \
      -d '{"login": "<user>", "token": "<сохраненный-токен>"}'
  3. Save the recovery_token from the JSON response — this is the only copy of the next token.

  4. The lock is removed automatically.

After that, log in normally and change the affected user’s password.

After the incident

  1. Ensure that the new recovery token is saved in the password manager.

  2. Review the following log lines in the incident window:

    • recovery token used

    • recovery token rejected

    Each entry must map to a known operator.

  3. If the original token may have been compromised (transmitted over an unreliable channel, caught in a screen record, etc.), issue a new token to invalidate the rotated copy.

  4. Match the anti-pickup protection thresholds to the observed traffic, primarily these:

    • TNGRI_LOGIN_THROTTLE_MAX_FAILURES

    • TNGRI_PASSWORD_POLICY_MAX_FAILED_LOGINS

    Raise them if necessary.