Идентификация - процедура распознавания субъекта по его идентификатору
Компьютеры не умеют распознавать людей или другие объекты, поэтому нужна вещь, которая бы олицетворяла субъект в информационной системе. Идентификатором может быть номер телефона, номер паспорта или адрес электронной почты
Аутентификация - процедура проверки подлинности субъекта. Проверить можно тремя способами:
Авторизация - это предоставление доступа к какому-либо ресурсу, например, к панели управления магазина
Обычно, чтобы усилить безопасность, применяют многофакторную аутентификацию - в ней субъекту нужно несколькими способами подтвердить, что именно он является пользователем. Наиболее распространена двухфакторная аутентификация (2FA или Two-Factor Authentication): например, сначала пользователь вводит пароль от учетной записи, а затем прикладывает отпечаток пальца
Также выделяют многоэтапную аутентификацию - процесс, в котором проверяется подлинность по одному фактору несколько раз, например, по паролю и пришедшему коду на электронную почту
Выбор подхода к тому, как проводить аутентификацию, зависит от желаемой степени защищенности ресурса. Например, если требуется защитить информационный форум, то достаточно будет пароля, однако если потенциальный ущерб от взлома будет большим, то следует внедрить многофакторную аутентификацию
Стандартная схема аутентификации по логину и паролю применительно к веб-приложениям может имплементироваться разными способами
При обращении к защищенному ресурсу сервер отправляет HTTP-ответ, содержащий статус 401 Unauthorized и заголовок WWW-Authenticate, где указана схема аутентификации
Далее браузер отображает свое диалоговое окно, где пользователь вводит логин (например, username) и пароль (password). После этого браузер каждый раз при доступе к ресурсу отправляет эти данные в заголовке Authorization в HTTP-запросе. После этого сервер решает, предоставлять доступ или нет

Сами логин и пароль могут храниться внутри заголовка несколькими способами (их называют схемами):
Basic (Базовая схема)
В ней данные аутентификации представляются в виде строки username:password в кодировке Base64, использующей буквы латинского алфавита, цифры и 2 специальных символа
Кодировка Base64 обратима, поэтому, если общение идет через протокол HTTP, то логин и пароль видны всем участникам сети.
По этой причине схему Basic нужно всегда использовать в связке с HTTPS, который шифрует заголовки
Digest (от англ. переваривать)
Схема Digest работает так: сервер шлет клиенту уникальное число nonce, далее клиент использует username, password, nonce, URI ресурса и другие параметры для вычисления хеша, используя функцию MD5 или SHA-256
Такая схема лучше, чем Basic, но уязвима к атакам “человек посередине” (man-in-the-middle attack, MITM): посредник может перехватить ответ сервера, а котором он говорит использовать схему Digest, и отправить клиенту ответ с просьбой использовать Basic, тем самым получив его пароль
NTLM (New Technology LAN Manager)
NTLM - семейство протоколов аутентификации, созданный компанией Microsoft
В нем пароль не передается напрямую, а тоже как хеш от пароля и случайного числа сервера
NTLM встроен в экосистему Windows и преимущественно используется для аутентификации пользователей Windows Active Directory
NTLM не защищен к атаке на хеш, ретрансляции аутентификации и подбору пароля
HTTP Negotiate
Далее появился протокол Kerberos, который намного безопаснее NTLM, из-за чего появилась схема Negotiate - клиент, отправляя запрос серверу, передает, какой протокол он поддерживает NTLM или Kerberos
HTTP Negotiate также называют SPNEGO (Simple and Protected GSS-API Negotiation Mechanism)
Также Kerberos поддерживает технологию единого входа (Single Sign-On, SSO): при переходе из одного портала в другой пользователь может повторно не проходить аутентификацию, используя токен первого портала
Важно заметить, что при использовании HTTP-аутентификации единственный способ выйти из учетной записи - это закрыть окно браузера
Далее пришли к тому, что можно создать форму на HTML-странице, где пользователь вводит логин, пароль (и дополнительно другие данные), которые отправляются на сервер для аутентификации. В случае успеха веб-приложение генерирует токен сессии (число, по которому происходит авторизация) и сохраняет его в куки. После этого при каждом запросе клиент отправляет на сервер куки, содержащие токен сессии

Токен сессии создается двумя способами:
Как зашифрованный объект, содержащий данные о пользователе
Такой подход позволяет реализовать stateless-архитектуру сервера (без хранения состояний), однако требует механизма обновления токена по истечении срока действия
Вместо пароля, который задается пользователем и зачастую бывает слишком легким к тому, чтобы его подобрать, можно использовать сертификат. Работает это так:
Клиент (и опционально сервер) имеет свои публичный и приватный ключи
Клиент (или сервер) запрашивает свой сертификат у центра сертификации - для этого создается запрос подписи сертификата (Certificate Signing Request, CSR). Этот запрос подписи подписывается приватным ключом клиента (или сервера): от всего запроса берется хеш, который шифруется с помощью приватного ключа
Центр сертификации, зная публичный ключ клиента, переданный в запросе, может расшифровать хеш и сопоставить с тем, что получился из всего сертификата, чтобы проверить, что клиент является владельцем ключей

По стандарту X.509 сертификат содержит:
Расширения (Extensions) - важные дополнительные параметры, которые определяют, для чего можно использовать данный сертификат. Например:
docs.example.comПриватные ключи клиента и центра сертификации остаются на соответствующих устройствах (например, на компьютере или специальной USB-флешке) и не сообщаются никому, тогда как публичные свободно передаются
У такого подхода есть недостатки:
Проверка по сертификату используется в протоколе TLS (Transport Layer Security), который основан на устаревшем протоколе SSL (Secure Sockets Layer) и на основе которого работает HTTPS (HTTP Secure):
Клиент, зная публичные ключи центров, должен проверить, является ли сервер подлинным владельцем сертификата путем проверки:
Аналогично работает mTLS (Mutual TLS) - клиент и сервер обмениваются своими сертификатами, проверив которые, они могут убедиться, что за клиентом стоит подлинный владелец, а сервер не выдает себя за злоумышленника
Вместе с аутентификацией по паролю для большей безопасности применяют аутентификацию по одноразовому паролю. При таком подходе в случае ввода правильного пароля приложение попросит пользователя ввести одноразовый пароль
Такой пароль может быть создан:
Одноразовые пароли обычно используются для подтверждения важных операций
Для API применяют другой подход: вместо логин и пароля ключ доступа (или API-ключ), который является длинной уникальной строкой и по сути заменяет логин и пароль
При идентификации сервер генерирует такой ключ пользователю, который дальше сохраняет его и пользуется им для доступа к сервису. Сервер же может ввести статистику операций, которые производил пользователь с этим ключом (например, для выставления лимита запросов)
Такой ключ:
Такой ключ может быть передан в URL-запросе, HTTP-заголовке или в теле запроса и обязательно в безопасном соединении через HTTPS
Для небезопасных соединений ключ состоит из двух частей: приватная и публичная. При запросе сервер отправляет уникальное число nonce (или можно использовать временную метку), которую клиент подписывает своим приватным ключом. Сервер с помощью публичного ключа может проверить подлинность клиента
В другом подходе применяются токены. Приложение может делегировать аутентификацию другому приложению, а пользователя попросить войти в изначальное приложение через другое (так работает аутентификация через Google и другие сервисы)
Приложение, которое предоставляет аутентификацию (так называемый поставщик идентификации, Identity Provider), предоставляет достоверные сведения о пользователе в виде токена, а стороннее приложение использует этот токен для аутентификации и авторизации. Пользователю, чтобы войти в стороннее приложение, нужно пройти аутентификацию в поставщике идентификации, который генерирует токен для стороннего приложения

В браузере же веб-приложения способны перенаправлять на сайт поставщика и обратно на сайт стороннего приложения
Сам токен содержит информацию о том, кто его сгенерировал, кто получатель, срок действия и так далее, а также подпись токена. При аутентификации проверяется, что токен выдан доверенным поставщиком идентификации, токен предназначен этому приложению, срок токена еще не истек, а подпись действительна
Есть несколько форматов токена:
Simple Web Token (SWT) - формат, состоящий из последовательных пар ключ-значение. Выглядит SWT так:
Issuer=http://auth.myservice.com&
Audience=http://myservice.com&
ExpiresOn=1435937883&
UserName=John Smith&
UserRole=Admin&
HMACSHA256=KOUQRPSpy64rvT2KnYyQKtFFXUIggnesSpE7ADA4o9w
JSON Web Token (JWT) - формат, состоящий из трех блоков: заголовка, набора полей и подпись. Заголовок и набор полей представляются в виде JSON, закодированного в кодировке Base64. Набор полей определяет, кто выдал токен, кому и для чего
Выглядит JWT так: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30
Блоки разделены между собой точками. При декодировке получается заголовок:
{
"alg": "HS256",
"typ": "JWT"
}
Набор полей:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"iat": 1516239022
}
И подпись: a-string-secret-at-least-256-bits-long
Security Assertion Markup Language (SAML) определяет токены (так называемые SAML assertions) в формате XML, включающем информацию о токене и набор дополнительных утверждений о пользователе
В отличие от предыдущих форматов, SAML-токены содержат механизм для подтверждения владения токеном, что позволяет предотвратить перехват токенов через атаку “человек по середине” при использовании незащищенных соединений
Разберем стандарты, определяющие аутентификацию по токену, взаимодействие между приложения и протоколы:
SAML (Security Assertion Markup Language)
Этот стандарт поддерживает много различных сценариев интеграции систем. Он основан на:
WS-Trust и WS-Federation (от Web services - Security)
Эти стандарты разрабатываются группой компаний Microsoft, IDM, VeriSign и используются преимущественно в корпоративных сценариях
Стандарт WS-Trust описывает интерфейс сервиса авторизации - он работает по протоколу SOAP и поддерживает создание, обновление и аннулирование токенов. При этом стандарт допускает использование токенов различного формата (обычно используется SAML Assertions)
Стандарт WS-Federation касается механизмов взаимодействия сервисов между компаниями, в частности, протоколов обмена токенов. Среди прочего, стандарт WS-Federation определяет формат и способы обмена метаданными о сервисах, функцию единого выхода из всех систем и другое
OAuth 2.0 и OpenID Connect
Стандарт OAuth (Open Authorization) определяет механизм получения доступа одного приложения к другому от имени пользователя
Первая версия стандарта разрабатывалась в 2007-2010 годах. Версия 2.0 была опубликована в 2012 году как расширение и упрощение
Процесс аутентификации состоит из нескольких шагов:
Стандарт описывает четыре вида грантов, которые определяют возможные сценарии применения:
Код авторизации (Authorization Code) - этот грант пользователь может получить от сервера авторизации после успешной аутентификации и подтверждения согласия на предоставление доступа. Такой способ наиболее часто используется в веб-приложениях
Неявный сценарий (Implicit) применяется, когда у приложения нет возможности безопасно получить токен от сервера авторизации (например, JavaScript-приложение в браузере) - в этом случае грант представляет собой токен, полученный от сервера авторизации, без обмена кода авторизации на сам токен
Учетные данные паролей владельца ресурса (Resource Owner Password Credentials) - такой грант представляет собой логин и пароль пользователя. Может применяться, если приложение является интерфейсом для сервера ресурсов
Учетные данные клиента (Client Credentials) - в этом случае нет никакого пользователя; само приложение собирается получить доступ к своим ресурсам при помощи своих ключей доступа
Стандарт не определяет формат токена, который получает приложение, поэтому ни токен, ни грант сами по себе не могут быть использованы для аутентификации пользователя
Однако если приложению необходимо получить достоверную информацию о пользователе, существуют несколько способов это сделать. Зачастую API сервера ресурсов включает операцию, предоставляющую информацию о самом пользователе (например, эндпоинт /me). Приложение может выполнять эту операцию каждый раз после получения токена для идентификации клиента - такой метод иногда называют псевдоаутентификацией
Вместо псевдоаутентификации можно использовать стандарт OpenID Connect, разработанный как слой идентификации поверх OAuth. В соответствии с ним, сервер авторизации предоставляет дополнительный токен идентификации в формате JWT, который содержит набор полей с информацией о пользователе