Start learning free

LESSON 86 OF 173 · BACKEND: USERS AND SECURITY

Never Store Passwords in C#

Practice

Until now, sign-up wrote the password itself into the users table. If that table ever leaks, every account is open, and many people use the same password on other sites too. A shop should never store passwords.

Hashes: store a hash instead, a one-way scramble of the password: easy to compute, no way back. The helper GeneratePasswordHash, already above the routes, hashes with Rfc2898DeriveBytes.Pbkdf2 and also mixes in a random salt from RandomNumberGenerator, so the same password gives a different result every time:

Console.WriteLine(GeneratePasswordHash("tulip7"));   // pbkdf2:sha256:600000$...$...
Console.WriteLine(GeneratePasswordHash("tulip7"));   // another salt, another hash

The result holds the method, the salt and the hash, split by $. The tests read the table through GET /check/users, a route the course adds for checking, which shows each different salt and hash as a numbered label. With your changes, the test requests get:

POST /register  {"email": "ana@example.com", "password": "secret123"}  →  201  {"email": "ana@example.com", "id": 1}
POST /register  {"email": "ana@example.com", "password": "hello456"}   →  409  {"error": "Email already registered"}
POST /register  {"email": "ben@example.com", "password": "secret123"}  →  201  {"email": "ben@example.com", "id": 2}
GET /check/users  →  200  [{"email": "ana@example.com", "id": 1, "password_hash": "pbkdf2:sha256:600000$<salt 1>$<hash 1>"},
                           {"email": "ben@example.com", "id": 2, "password_hash": "pbkdf2:sha256:600000$<salt 2>$<hash 2>"}]

Ana and Ben chose the same password, yet their rows share nothing but the method.

Your task: name the last column of the users CREATE TABLE password_hash instead of password, compute passwordHash in /register with GeneratePasswordHash, and save the hash instead of the password: an INSERT with the placeholder $password_hash, and its value. The helper and using System.Security.Cryptography; are already there.


Assignment
Follow the Coding Tutorial to store a salted hash at sign-up instead of the password.


Hint
Hash only after the 409 check. The $email value from the SELECT is still on cmd, so the INSERT can use it; give $password_hash the value passwordHash with cmd.Parameters.AddWithValue, or SQLite refuses to run the INSERT.


STEP 1 OF 4
    Ctrl + Enter to check

    Auth Hash Passwords in C#

    Keep going with C#1,600+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free