Вопрос: Как устроена авторизация по паролю в web-приложениях?

Лучший ответ:
Обычно разделяют сессии и авторизацию:Сессия. Чтобы реализовать сессии сервер при первом соединении с клиентом может генерировать некоторый случайный токен и устанавливать его в куки. Тут важно, что куки должны передаваться по защищённому каналу (HTTPS). Таким образом можно сохранять некоторую информацию о сессии в базе данных или же в самих куки, но тогда нужно подписывать куки, чтобы пользователь не мог их изменять.
В любом случае, сервер будет хранить информацию о активных сессиях в БД.
Подписать куки можно, например, добавив в них помимо нужной вам информации какой-нибудь HMAC.Авторизация. Сервер никогда не хранит пароли. В базе данных хранят логин и хеш пароля (на самом деле нет). Для авторизации пользовтель передаёт логин и пароль (HTTPS). Сервер вычисляет хеш от пароля и, если он совпадает, сессия помечается как авторизованная.Соль. Теперь представим, что вы действительно храните логин и хеш пароля в таблице:login | pass_hash
------+----------
vasya | 4B32E1C...
В идеальном мире это бы неплохо работало. Но в реальном мире 90% ваших пользователей будут иметь пароль вида 12345, password, password123, etc. Соответственно в базе данных будет много одинаковых хешей и злоумышленнику не составит труда быстро подобрать пароли большинства ваших пользователей.
Для этого для каждого пользователя сервер сохраняет некоторые уникальные случайные данные (соль). А вместо хеша пароля хранится hash(pass + salt).login | salt   | hash
------+--------+-----
vasya | 4B3... | 2A3B9...
Таким образом усложняется перебор паролей по словарю.Хеш. Возможно вы где-то видели или слышали про MD5. Так вот, MD5 на сегодняшний день не является надёжной криптографической хеш функцией и даже если вы примените MD5 сто или тысячу раз, это не сильно изменит ситуацию. На сегодняшний день рекомендуется использовать SHA-2 или SHA-3.P. S.  Соль и токены обязательно должны быть сгенерированы с помощью CSPRNG.

Худший ответ:
Обычно делают так: есть база данных с таблицей пользователей со следующей структурой
id username password
где id - primary key(целочисленное значение уникальное для каждого пользователя)
username понятно
password - хеш пароля, причём к этому хешу добавляется соль, общая для всей базы(хранить где-нибудь в конфиге приложения, чтоб при доступе к базе её было не найти) и какая-нибудь для пользователя, чтоб у разных пользователей пароль qwerty превращался в разные хеши. 
И также таблица сессий.
session_key expiration_time user_id
session_key рандомная строка(например Ku0peepia3ialete3uawai9oK3Koh2ni), которая хранится в куках пользователя
expiration_time timestamp когда сессия заканчивается(важно на банковских приложениях например)
user_id - id пользователя, которому принадлежит сессия.
Также можно добавить другие данные, как например ip, user-agent и т.д.
Когда пользователь ввёл логин и пароль в форму и нажал "войти", на сервер отправляется POST запрос с логином и паролем, сервер принимает его, хеширует пароль и проверяет в базе, есть ли такая пара, если есть, создаётся сессия и возвращается пользователю в куках(хедер Set-Cookie), клиент устанавливает их себе и при следующих запросах отправляет сессию в хедере Cookie, либо берётся та, которую отправил пользоваль и привязывается к аккаунту. Когда пользователь заходит в админку, сервер смотрит, есть ли такая сессия и имеет ли права на доступ в админку её владелец, если нет, то возвращает ошибку.