Skip to content
Language:en Author:Laborci Gergely
web-security

Passwords, multi-factor authentication, and session protection

Objectives

By the end of the lesson, you can say how a password must be stored and why a fast hash is not good, what multi-factor authentication (MFA) means and what it does not solve, and what must be done to protect the session identifier.

Why does the security of login not end with checking the password?

The security of login consists of several links: the storage of the password, the second factor, the handling of the session identifier, and logout. One weak link is enough for account takeover. The attacker can steal the password from a database leak, guess it, phish it, or obtain the session identifier valid after login. Each needs a separate defense.

Checking and storing the password

At login the server compares the given password with the verification value stored earlier. The password must not be stored in readable form, because a database leak would reveal it at once. Storage requires a password hash: a one-way transformation from which the password cannot be restored.

But it matters what kind of hash. A fast, general-purpose hash (for example SHA-256, Secure Hash Algorithm) is good for files precisely because it is fast; for passwords this is the problem, because the attacker can try a great many guesses quickly. We tried it on the same machine, on one core:

SHA-256:  20000 tries    in 16 ms   (~1 288 269 tries/s)
scrypt (N=2^17, r=8, p=1):  20 tries  in 3457 ms  (~6 tries/s)

The fast hash is more than two hundred thousand times faster. An attacker who has obtained the hashes can try several million passwords per second with plain SHA-256, and only a few with the costly procedure. That is why passwords need a procedure designed specifically for this, slow and resource-intensive.

OWASP's password storage guide recommends the following order:

  • Argon2id (primary): at least 19 MiB of memory, 2 iterations, parallelism of 1;
  • scrypt, if Argon2id is not available (at least N=2^17, r=8, p=1);
  • bcrypt for legacy systems (with a work factor of at least 10, and a 72-byte password length limit, because it truncates anything longer);
  • PBKDF2, if it is mandatory for compliance reasons (PBKDF2-HMAC-SHA256 with at least 600,000 iterations).

(PBKDF2: Password-Based Key Derivation Function 2.) The measurement above was made with scrypt, because according to our try there is no argon2Sync function in the built-in crypto module of Node.js 24.4.1; in a production system a proven library must be used, never a home-made implementation.

Salt

Every password has a unique, random salt. This prevents the use of precomputed tables, and prevents the attacker from cracking many hashes in one go. Tried with the same password and two different salts:

same password, two different salts:
  0c4b569047729615f0fccb2af461261c...
  44b17cf13358073209130e40f14c5c1d...

The stored values for the same passwords differ, so from a leak it cannot be seen who used the same password. Most libraries manage the salt automatically.

flowchart LR
    P[User's password] --> H[Slow password hash + unique salt]
    H --> D[(Stored verification value)]
    X[Password given at login] --> V[Verification by the same procedure]
    D --> V
    V --> R{Match?}

Password use and recovery

According to NIST's (National Institute of Standards and Technology) authentication guideline (SP 800-63B), for passwords length counts: for a standalone password at least 15 characters, with a permitted length of at least 64 characters; mandatory character-mix rules must not be imposed; regular password change must not be forced (only on compromise); the new password must be checked against lists of known, common, or leaked passwords; and password managers and pasting must be allowed. On the server side, limiting the number of attempts and detecting incidents are important.

Password reset can be an account-takeover route just as login can, so the recovery process cannot be weaker than login.

Multi-factor authentication

MFA (Multi-Factor Authentication) combines at least two different factor families: something we know (a password), something we possess (an authenticator device, a security key), or something that is tied to the person (biometrics). Two passwords requested one after the other are not two factors. MFA reduces the value of a stolen password, but does not make account takeover impossible: phishing, session theft, or poorly protected recovery remain risks.

The strength of the methods differs. According to NIST's guideline, passwords, one-time codes (OTP: one-time password), and codes sent by SMS or another channel are not phishing-resistant, because the user can be talked into passing them on. Phishing-resistant is cryptographic authentication bound to the given website (in the browser, to the origin), such as a security key based on WebAuthn/FIDO2. The point from the course's perspective: the factor should really be independent evidence, and the recovery route should not bypass the login protection more easily.

The session as a post-login key

After successful authentication the session identifier or access token proves in later requests that the client is continuing an already logged-in flow (7.2, 7.3). Whoever obtains this value can use the session without knowing the password. Therefore:

  • the identifier should be hard to guess (random, long enough);
  • at login and at a change of privilege state it is worth issuing a new identifier (against session fixation);
  • there should be expiry and server-side invalidation;
  • the cookie should be Secure (binds it to a protected connection), HttpOnly (JavaScript cannot read it directly), and SameSite (regulates cross-site sending). These act against separate risks: HttpOnly does not stop every operation of a script running on a compromised page (8.3), and SameSite is not complete CSRF protection (8.4).

Keeping an authentication token in the localStorage or sessionStorage of the browser, reachable from JavaScript, is risky, because in case of XSS the script can access it; the decision about storage must be made on the basis of the threat model (8.1).

Logout and time limits

Depending on the authentication levels, NIST prescribes different re-authentication time limits (shorter at higher levels), which shows well that time limits are proportional to risk.

Worked example: logging in to Kurzuspont

Element Decision
Password storage Argon2id or scrypt, a unique salt, with a proven library.
Password requirement At least 15 characters, long passwords, leaked passwords banned, no mandatory character mix or forced change.
Attempts Limiting and an alert for many failed logins (chapter 10: observability).
MFA Mandatory for instructors, recommended for students; a phishing-resistant method preferred.
Recovery A one-time, short-lived link; not weaker than login.
Session Random identifier, new at login, HttpOnly; Secure; SameSite, short expiry, server-side logout.

Common misconceptions

Statement Clarification
"A password hashed with SHA-256 can be stored safely." For passwords a costly procedure designed for the purpose and a unique salt are needed.
"After MFA the session no longer matters." An obtained session identifier may still be usable.
"HttpOnly defends against every browser attack." It limits only the direct script access to the cookie.
"Logout is only client-side state." The server must also invalidate the accepted access.
"An SMS code is phishing-resistant." According to NIST, such codes can be passed on, so they are not.
"A complicated password is better than a long one." Length counts; NIST does not prescribe a mandatory character mix.

In brief

  • Store the password with a slow, purpose-designed hash and a unique salt (Argon2id, scrypt); a fast hash (SHA-256) is not good.
  • The tried fast hash was ~1.3 million tries/s, scrypt ~6 tries/s on the same machine.
  • MFA combines different factor families; the strongest are the phishing-resistant methods.
  • The session identifier is a post-login key: random, new at login, expiring, invalidatable on the server.

Review questions

  1. Why is plain SHA-256 not good for password storage?
  2. What does the salt protect?
  3. What is the difference between MFA and two passwords in a row?
  4. Why must logout invalidate the session on the server too?

Learning resources

Prerequisites (2)

  • authentication
  • session

Teaches (3)

  • password storage
  • multi-factor authentication
  • session protection