Аутентификация vs авторизация
Аутентификация и авторизация: «кто ты» против «что тебе можно».
Суть: аутентификация устанавливает личность пользователя (кто он), авторизация решает, что ему разрешено делать. Это два разных шага: сначала узнаём пользователя, потом проверяем его права.
Эти слова часто путают, но разница принципиальна. Аутентификация — это вход (логин/пароль, токен): система убеждается, что вы тот, за кого себя выдаёте. Авторизация — это контроль доступа: даже залогиненный пользователь не имеет права удалять чужие данные, если он не админ.
Два понятия
| Аспект | Аутентификация | Авторизация |
|---|---|---|
| Вопрос | Кто ты? | Что тебе можно? |
| Когда | Первой | После аутентификации |
| Результат | Личность (Claims) | Доступ разрешён/запрещён |
| Пример | Проверка токена | Проверка роли Admin |
Claims — кирпичики личности
После аутентификации пользователь представлен набором claims (утверждений): «Id = 42», «Email = [email protected]», «Role = Admin». Авторизация принимает решения, читая эти claims.
Запрос с токеном
|
v
[Authentication] токен валиден? -> да -> Claims: { id:42, role:Admin }
| нет -> 401 Unauthorized
v
[Authorization] нужна роль Admin? -> есть -> пропустить
нет -> 403 Forbidden
|
v
[Эндпоинт]
Как работает под капотом
Middleware UseAuthentication читает учётные данные из запроса (например токен из заголовка), проверяет их и, если всё верно, наполняет HttpContext.User объектом ClaimsPrincipal с claims. Дальше UseAuthorization и атрибуты [Authorize] читают этот User и сверяют с требованиями (нужна роль/политика). Важно различать коды: 401 Unauthorized — «ты не представился» (нет/плохой токен), 403 Forbidden — «представился, но прав не хватает».
Частые ошибки
- Путать 401 и 403. 401 — не аутентифицирован, 403 — аутентифицирован, но нет прав. Возврат не того кода путает клиентов.
- Авторизация на фронтенде «вместо» бэкенда. Скрытая кнопка не защита — проверку прав делает сервер.
- Считать, что логин равен полному доступу. Аутентификация не отменяет проверку прав на каждое действие.
Best practices
- Чётко разделяйте два шага и ставьте middleware в правильном порядке (Authentication, затем Authorization).
- Стройте авторизацию на claims/политиках, а не на разбросанных по коду условиях.
- Защищайте каждый чувствительный эндпоинт явно — «по умолчанию закрыто» безопаснее.
Claims, схемы и единый ClaimsPrincipal
После успешной аутентификации пользователь в ASP.NET Core представлен объектом ClaimsPrincipal — набором claims (утверждений вида «ключ-значение»): идентификатор, имя, email, роли, любые кастомные атрибуты. Этот объект лежит в HttpContext.User и доступен всему конвейеру и эндпоинтам. Авторизация не «логинит» заново — она читает уже готовые claims и сверяет их с требованиями. Такое разделение позволяет менять способ аутентификации (cookie, JWT, внешний провайдер) не трогая логику авторизации: она всегда работает с единым ClaimsPrincipal.
Способ аутентификации задаётся схемой: cookie-схема (классические веб-сайты с сессией в куке), JWT Bearer (stateless-API), OAuth/OpenID Connect (вход через Google, корпоративный SSO). Схем может быть несколько одновременно, и эндпоинт способен указывать, какая из них применима. Но на выходе у всех одно — наполненный ClaimsPrincipal.
Принцип наименьших привилегий и многоуровневая защита
Авторизацию строят по принципу наименьших привилегий: по умолчанию доступ закрыт, а открывается ровно то, что нужно конкретной роли или пользователю. Удобный приём — глобальный [Authorize] на всё приложение и точечные [AllowAnonymous] на публичные эндпоинты (логин, регистрация, health). Так невозможно «забыть» защитить новый чувствительный эндпоинт — он закрыт автоматически, пока вы явно не разрешите. Это сдвигает класс ошибок «случайно оставил открытым» из разряда возможных в разряд исключённых по конструкции.
Критично понимать, что авторизация на клиенте — это лишь удобство интерфейса, а не защита. Скрытая кнопка «удалить» не мешает отправить DELETE-запрос напрямую. Настоящая проверка прав происходит только на сервере, на каждом чувствительном действии. И различие кодов 401 (не аутентифицирован — иди представься) и 403 (аутентифицирован, но прав нет) — не формальность: по ним клиент выбирает, отправить пользователя на логин или показать «доступ запрещён». Возврат не того кода ломает это поведение.
Итог: аутентификация отвечает «кто ты», авторизация — «что можно»; они идут по порядку и оперируют claims. Дальше — как это реализуют через JWT-токены.