Some standard, obvious (or not so) best-practices, based on defense-in-depth and security effort based on impact risk:
Hash passwords using a real pbkdf like argon2 in JS or native code client-side, using sensible mem-/cpu-/gpu-fpga-/asic-hard params, because passwords should never go over the wire in any form.
Use nonces where available.
Fixed-time compare hashes server-side, with exponential back-off.
2FA tokens should be stored server-side encrypted, only decrypted when needed to generate a challenge code and then securely erased, where available.
Prefer TOTP to SMS 2FA.
Lock down admin access to all production boxes to a dedicated private vlan or physical net behind ssh/vpn bastion (jump box) which has per-user ssh keyed logins.
Use gpg user-based, single packet authorization secure port knocking to allow access to ssh / vpn through bastion. Paranoia around admin access isn’t paranoid enough since a compromise would cost much time and money in many unforseen ways.
No root passwords, ssh keys only. If absolutely required, store N-keyed using something like vault.
Don’t give too many people access they don’t need, but also don’t micromanage.
No shared accounts or ssh keys for people; service accounts for unattended services only.
Audit and disable/remove creds/privs not being used.
Ssh/gpg/tls private keys must be stored securely.
Lock-down, audit, transparent proxy, SPI, scrub nearly all external ports/data.
Never trust external, unsecured data.
—-
HTH