HTTP аутентификация – HTTP | MDN

Аутентификация на основе токенов

Этот способ был введен для устранения основанного на куках аутентификации. Особенности подхода – требуется ручная реализация и токены сохраняются на стороне клиента.

Когда вы входите в
веб-приложение, сервер проверяет учетные данные и отправляет зашифрованный
токен в браузер. Браузер сохраняет токен и добавляет его в заголовок авторизации
будущих запросов.

Стандартные реализации
токен-подхода в разы сложнее описанных выше. Например, в
OpenID Connect применяется несколько потоков аутентификации для различных сценариев использования. Чтобы лучше понять, как работают токены, разобьем процесс на четыре части и в качестве примера используем JWT (JSON Web Token) – наиболее широко используемый стандарт.

Что документируется в разделе аутентификации

В документации API не нужно подробно объяснять внешним пользователям, как работает аутентификация. Отсутствие объяснений внутренних процессов аутентификации, является лучшей практикой, поскольку хакерам будет сложнее злоупотреблять API.

Тем не менее нужно объяснить необходимую информацию:

  • как получить API ключ;
  • как пройти аутентификацию запроса;
  • сообщения об ошибках, связанных с неверной аутентификацией;
  • чувствительность информации аутентификации;
  • период действия токена доступа (авторизации).

Если есть открытый и закрытый ключи, нужно объяснить, где следует использовать каждый ключ, и отметить, что закрытые ключи не должны использоваться совместно. Если разные уровни лицензий предоставляют разный доступ к вызовам API, эти уровни лицензирования должны быть явно указаны в разделе авторизации или в другом месте.

Поскольку раздел API ключей важен, и нужен разработчикам до того, как они начнут использовать API, этот раздел должен быть в начале руководства.

Введение в аутентификацию и авторизацию

Аутентификация и авторизация в Web API имеет некоторые особенности в отличие от ASP.NET MVC. Здесь фактически нам доступны три вида аутентификации:
стандартная через куки, через внешние сервисы и аутентификация с помощью токена.

Похожее:  Шпаргалки по безопасности: JWT / Хабр

В то же время Web API и ASP.NET MVC имеют ряд общих моментов.

Абстрактное описание протокола

Теперь, когда у нас есть представление о ролях, используемых в OAuth, рассмотрим диаграмму их взаимодействия друг с другом.

Рассмотрим описание последовательности шагов на этой диаграмме:

  1. Приложение запрашивает у пользователя авторизацию на доступ к серверу ресурсов.
  2. Если пользователь авторизует запрос, приложение получает разрешение на авторизацию (authorization grant).
  3. Приложение запрашивает авторизационный токен у сервера авторизации (API) путём предоставления информации о самом себе и разрешении на авторизацию от пользователя.
  4. Если подлинность приложения подтверждена и разрешение на авторизацию действительно, сервер авторизации (API) создаёт токен доступа для приложения. Процесс авторизации завершён.
  5. Приложение запрашивает ресурс у сервера ресурсов (API), предоставляя при этом токен доступа для аутентификации.
  6. Если токен действителен, сервер ресурсов (API) предоставляет запрашиваемый ресурс приложению.

Фактический порядок шагов описанного процесса может отличаться в зависимости от используемого типа разрешения на авторизацию, но в целом процесс будет выглядеть описанным образом. Далее мы рассмотрим различные типы разрешений на авторизацию.

Hmac (код авторизации сообщений на основе хэша)

HMAC расшифровывается как Hash-based message authorization code – код авторизации сообщений на основе хэша и является более строгим типом аутентификации, более распространенным в финансовых API. В HMAC только отправитель, и получатель знают секретный ключ, который больше неизвестен никому.

Затем сообщение кодируется секретным ключом и проходит через алгоритм безопасного хеширования (SHA – secure hashing algorithm). (Хеш – это зашифрованная строка на основе алгоритма.) Результирующее значение, называемое сигнатурой, помещается в заголовок запроса.

Сервер API (получатель), получая запрос, принимает те же системные свойства (отметка времени запроса плюс идентификатор учетной записи) и использует секретный ключ (который известен только запрашивающей стороне и серверу API) и SHA для генерации одной и той же строки. Если строка соответствует подписи в заголовке запроса, запрос принимается. Если строки не совпадают, запрос отклоняется.

Вот диаграмма, отображающая процесс авторизации HMAC:

Важным моментом является то, что секретный ключ (критический для восстановления хэша) известен только отправителю и получателю. Секретный ключ не включается в запрос. Безопасность HMAC используется, когда нужно убедиться, что запрос является подлинным и не может быть подделан.

Сервер проверяет учетные данные, генерирует токен, подписывает его секретным ключом и отправляет в браузер

При передаче обычно необходимо
использовать шифрование (например, SSL) для защиты канала.

На стороне сервера можно
использовать библиотеку NPM (такую как jsonwebtoken) для
создания токенов:

Сервер отправляет файл cookie браузеру, включая его в заголовок Set-Cookie

В дополнение к этому в
cookie могут храниться такие сведения, как дата истечения срока действия, домен
и возраст. Пример ответа с несколькими заголовками cookie будет выглядеть
следующим образом:

Сохранение токена в хранилище браузера и добавление в запросы с помощью JavaScript

Браузер может хранить
этот маркер в локальном хранилище, хранилище сеансов или в хранилище cookies.
Затем он будет добавлен в заголовок авторизации и отправлен на сторону сервера
для валидации запросов.

Добавление токена в заголовок должно быть реализовано с помощью JavaScript.

Authorization: Bearer <token>

Кроме того, можно использовать
функцию jwt.decode() из библиотеки jsonwebtoken для декодирования токена.

Браузер сохраняет cookie в хранилище и отправляет его с последующими запросами

Когда сервер получает запрос с cookie, он сравнивает идентификатор сеанса в файле cookie с сеансом в базе данных для валидации пользователя.

Найти все сохраненные в браузере файлы cookie можно в хранилище файлов cookie в разделе
приложения с помощью инструментов разработчика (devtools).

При выходе пользователя из системы токен вручную удаляется из хранилища

Как только пользователь выйдет из системы, необходимо вручную очистить находящийся в хранилище токен, чтобы сделать его недоступным для дальнейших запросов.

Мы разобрались, как
работает аутентификация на основе токенов, теперь рассмотрим фичи, плюсы и
минусы этой схемы.

Когда пользователь выйдет из системы, сервер удалит сеанс из базы данных

Как только пользователь
выйдет из системы, у сервера истечет срок действия файла cookie и сеанс в базы данных будет очищен. Браузер делает то же самое, удаляя файл cookie из хранилища.

Мы разобрались, как
работает аутентификация на основе cookie, теперь рассмотрим фичи, плюсы и
минусы этой схемы.

Amazon web services

авторизация амазон

Amazon использует HMAC. Процесс достаточно сложный, чтобы включить полноценную диаграмму, показать шаги, которые должны выполнить пользователи.

Api ключ

Большинство API требуют авторизации ключом API, чтобы использовать API. Ключ API представляет собой длинную строку, которую обычно включают либо в URL запроса, либо в заголовок запроса. Ключ API в основном служит способом идентификации лица, выполняющего запрос API (аутентифицируя для использования API). Ключ API также может быть связан с конкретным приложением, которое регистрируется.

Ключи APK используют строку в свойстве заголовка для авторизации запросов

API могут дать как открытый, так и закрытый ключ. Открытый ключ обычно включается в запрос, в то время как закрытый ключ рассматривается скорее как пароль и используется только при обмене данными между серверами. На некоторых сайтах документации API, при заходе на сайт, ключ API автоматически заполняется в примере кода и API Explorer.

Basic auth

Другой тип авторизации называется Basic Auth. С помощью этого метода отправитель помещает пару имя пользователя:пароль в заголовок запроса. Имя пользователя и пароль кодируются с помощью Base64, который представляет собой метод кодирования, который преобразует имя пользователя и пароль в набор из 64 символов для обеспечения безопасной передачи. Вот пример Basic Auth в заголовке запроса:

Cookie-based authentication

Аутентификация – это процесс обмена учетными данными для идентификации пользователя. При аутентификации на основе cookies уникальный идентификатор (файл cookie) создается на стороне сервера и отправляется в браузер.

Когда вы входите в веб-приложение, браузер получает файл cookie с сервера, сохраняет его и отправляет с каждым
последующим запросом, чтобы сервер мог убедиться, что запросы поступают от одного и того пользователя.

Чтобы лучше понять, как
работают файлы cookie, разобьем этот процесс на 5 частей.

Dropbox

Авторизация в Dropbox

Id-токены

ID-токены предоставляют информацию о событии аутентификации и идентифицируют пользователя. ID-токены предназначены для клиента. Они имеют фиксированный формат, понятный для клиента: клиент может извлечь идентифицирующую информацию из токена и таким образом аутентифицировать пользователя.

OIDC декларирует фиксированный формат для ID-токенов —

Json web token (jwt)

JSON Web Tokens (JWT, иногда произносится как «джот») составляются из трех URL-безопасных строковых сегментов, соединенных точками.

Аутентификация

Настройки аутентификации зачастую состоят из двух частей: настроек на стороне сервера и настроек на стороне веб-приложения, которое на этом сервере работает. Настройки безопасности веб-приложения не могут не взаимодействовать с настройками безопасности веб-сервера хотя бы по той причине, что веб-приложение не может не взаимодействовать с веб-сервером.

Мы с Вами не зря переключились на Tomcat, т.к. Tomcat имеет хорошо описанную архитектуру (см. “

“). Из описания этой архитектуры видно, что Tomcat как веб-сервер представляет веб-приложение как некоторый контекст, который и называют ”

“. Этот контекст позволяет каждому веб-приложению иметь свои настройки, изолированные от других веб-приложений. Кроме того, веб-приложение может влиять на настройки этого контекста. Гибко и удобно. Для более глубокого понимания рекомендуется к прочтению статья “

” и раздел документации Tomcat ”

“.

Как выше было сказано, наше веб-приложение может влиять на Tomcat Context нашего приложения при помощи файла

/META-INF/context.xml

. И одной из очень важных настроек, на которую мы можем повлиять, является Security Realms.

Security Realms

— это некоторая “область безопасности”. Область, для которой указаны определенные настройки безопасности. Соответственно, используя Security Realm мы применяем настройки безопасности, определённые для этого Realm. Security Realms управляются контейнером, т.е. веб-сервером, а не нашим веб-приложением.

” описывает Realm как набор данных о пользователях и их ролях для выполнения аутентификации. Tomcat предоставляет набор различных реализаций Security Realm’ов, одним из которых является ”

“.

Разобравшись немного с терминологией, давайте опишем Tomcat Context в файле

/META-INF/context.xml

Безопасность

Cookie не имеют надежной защиты от атак, и они в основном уязвимы для атак с использованием межсайтового скриптинга (XSS) и подделки межсайтовых запросов (CSRF).

Мы можем явно изменить заголовки файлов cookie, чтобы защитить их от таких атак.

Веб-приложение

Итак, нам понадобится веб-приложение. В его создании нам поможет система автоматической сборки проектов Gradle. Благодаря использования Gradle мы сможем при помощи выполнения небольших команд собирать Java проект в нужном нам формате, создавать автоматически нужную структуру каталогов и многое другое.

Подробнее про Gradle можно прочитать в кратком обзоре: “

” или в официальной документации ”

“.

Нам нужно выполнить инициализацию проекта (Initialization), а для этого в Gradle есть специальный плагин: ”

” (Init – сокращение от Initialization, легко запомнить).

Чтобы воспользоваться этим плагином, выполним в командной строке команду:

gradle init --type java-application

После успешного выполнения у нас появится Java проект.

Откроем теперь на редактирование билд скрипт нашего проекта. Билд скрипт — это файл с названием

build.gradle

, который описывает нюансы сборки (билда) приложения. Отсюда и название такое, билд скрипт. Можно сказать, что это скрипт сборки проекта.

Gradle — это такой универсальный инструмент, базовые возможности которого расширяются благодаря плагинам. Поэтому, в первую очередь обратим внимание на блок “plugins” (плагины):


plugins {
    id 'java'
    id 'application'
}

По умолчанию Gradle, в соответствии с указанным нами ”

--type java-application

“, выставил набор некоторых базовых плагинов (core plugins), то есть тех плагинов, которые входят в поставку самого Gradle. Если перейти на сайте

в раздел “Docs” (то есть документация), то слева в списке тем в разделе “Reference” мы видим раздел ”

“, т.е. раздел с описанием этих самых базовых плагинов. Давайте выберем именно те плагины, которые нам нужны, а не те, которые нам сгенерировал Gradle.

Согласно документации, ”

” обеспечивает базовые операции с Java кодом, такие как компиляция исходного кода. Так же, согласно документации, ”

” обеспечивает нас средствами для работы с “executable JVM application”, т.е. с java приложением, которые можно запустить как самостоятельное приложение (например, консольное приложение или приложение с собственным UI). Получается, что плагин “application” нам не нужен, т.к. нам не нужно самостоятельное приложение, нам нужно веб-приложение. Удалим его. А так же настройку “mainClassName”, которая известна только этому плагину.

Далее, в том же разделе “

“, где была приведена ссылка на документацию по Application Plugin, есть ссылка на Gradle War Plugin.

, как сказано в документации, предоставляет поддержку создания Java веб-приложений в формате war. В формате WAR означает, что вместо JAR архива будет создан WAR архив. Кажется, это то, что нам нужно. Кроме того, как сказано в документации, “The War plugin extends the Java plugin”. То есть мы можем заменить плагин java на плагин war. Следовательно, наш блок плагинов в итоге будет иметь следующий вид:


plugins {
    id 'war'
}

Так же в документации к “Gradle War Plugin” сказано, что плагин использует дополнительный “Project Layout”. Layout с английского переводится как расположение. То есть war plugin по умолчанию рассчитывает на существование некоторого расположение файлов, которые он будет использовать для своих задач. Использовать для хранения файлов веб-приложения он будет следующий каталог:

src/main/webapp

Поведения плагина описано так:

То есть плагин будет учитывать файлы из этого расположения при сборке WAR архива нашего веб-приложения.

Кроме того, в документации Gradle War Plugin’а сказано, что данный каталог будет “root of the archive”. И уже в нём мы можем создать каталог WEB-INF и добавить туда файл web.xml. Что это за файл такой?

web.xml

— это “Deployment Descriptor” или “описатель развёртывания”. Это такой файл, который описывает, как нужно настроить наше веб-приложение для работы. В этом файле указывается, какие запросы будет обрабатывать наше приложение, настройки безопасности и многое другое. По своей сути он чем-то похож на manifest файл из JAR файла (см. “

“). Manifest файл рассказывает, как работать с Java Application (т.е. с JAR архивом), а web.xml рассказывает, как работать с Java Web Application (т.е. с WAR архивом).

Само понятие “Deployment Descriptor” возникло не само по себе, а описано в документе “

“.

Любое Java веб-приложение зависит от этого “Servlet API”. Важно понимать, что это API — то есть это описание некоторого контракта взаимодействия. Веб-приложения — это не самостоятельные приложения. Они запускаются на веб-сервере, который обеспечивает сетевое взаимодействие с пользователями.

То есть веб-сервер это некоторый “контейнер” для веб-приложений. Это логично, т.к. мы хотим писать логику веб-приложения, т.е. какие странички увидит пользователь и как они должны реагировать на действия пользователя. И мы не хотим писать код того, как будет отправляться сообщение пользователю, как будут передаваться байты информации и другие низкоуровневые и очень требовательные к качеству реализации вещи.

Кроме того, получается, что веб-приложения все разные, а передача данных одинакова. То есть миллиону программистов пришлось бы писать для одной и той же цели код снова и снова. Поэтому за часть взаимодействия с пользователем и за обмен данными отвечает веб-сервер, а за формирование этих данных отвечает веб-приложение и разработчик.

А чтобы связать эти две части, т.е. веб-сервер и веб-приложение, нужен контракт их взаимодействия, т.е. по каким правилам они это будут делать. Чтобы как-то описать контракт, как должно выглядеть взаимодействие между веб-приложением и веб-сервером и придуман Servlet API.

Интересно, что даже если вы используете фрэймворки вроде Spring, то “под капотом” всё равно работает Servlet API. То есть вы используете Spring, а Spring за Вас работает с Servlet API.

Получается, что наш проект веб-приложения должен зависеть (depends on)

от Servlet API. В этом случае Servlet API будет зависимостью (dependency). Как мы знаем, Gradle в том числе позволяет декларативным образом описывать зависимости проекта. А то, каким образом можно управлять зависимостями, описывают плагины.

Например, Java Gradle Plugin вводит способ управления зависимостями “testImplementation”, который говорит, что такая зависимость нужна только для тестов.

А вот Gradle War Plugin добавляет способ управления зависимостями “providedCompile”, который говорит, что такая зависимость не будет включена в WAR архив нашего веб-приложения.

Почему мы не включаем Servlet API в наш WAR архив? Потому что Servlet API будет предоставлен нашему веб-приложению самим веб-сервером.

providedCompile

.

Таким образом, блок зависимостей (dependencies) будет иметь следующий вид:


dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
    testImplementation 'junit:junit:4.12'
}

Итак, вернёмся к web.xml файлу. По умолчанию, Gradle не создаёт никакой Deployment Descriptor, поэтому нам нужно сделать это самостоятельно.

Создадим каталог

src/main/webapp/WEB-INF

, а в нём создадим XML файл с названием

web.xml

.

Теперь давайте откроем саму спецификацию “Java Servlet Specification” и главу ”

“.

Как сказано в “14.3 Deployment Descriptor”, XML документ Deployment Descriptor’а описан схемой

Делегирование с областью видимости

Как API узнает, какой уровень доступа нужно дать приложению? Это определяется путем установления области видимости (scopes).

Область видимости «ограничивает, что именно приложение может делать в интересах пользователя». Она не позволяет выдать права, которых у пользователя уже нет. Например, если пользователь MyCalApp не имеет права создавать новые корпоративные аккаунты, область видимости гарантирует, что HireMe123 тоже не позволит пользователю создавать новые корпоративные аккаунты.

Области видимости делегируют контроль доступа самому API или ресурсу. За соответствие областей видимости правам пользователя отвечает API.

Давайте рассмотрим это на примере.

Я использую приложение HireMe123. HireMe123 хочет получить доступ к стороннему API MyCalApp для создания события в календаре от моего имени. Приложение HireMe123 уже запросило токен доступа к MyCalApp на сервере авторизации MyCalApp. В этом токене содержится важная информация:

  • sub: (мой пользовательский ID в MyCalApp);
  • aud: MyCalAppAPI (этот токен создан для доступа к API MyCalApp);
  • scope: write:events (область видимости предполагает, что HireMe123 может использовать API для записи событий в моем календаре).

HireMe123 посылает запрос к API MyCalApp с токеном доступа в заголовке авторизации. Когда API MyCalApp получает этот запрос, он видит, что в нем установлена область видимости write:events.

Но на MyCalApp содержатся аккаунты с календарями сотен тысяч пользователей. Поэтому, чтобы убедиться, что этот запрос от HireMe123 будет касаться только моих прав создавать события в моем аккаунте, промежуточное ПО API MyCalApp должно проверить не только область видимости, но и sub — идентификатор субъекта.

В контексте делегированной авторизации области видимости обозначают, что именно приложение сможет делать от имени пользователя. Это подмножество прав пользователя в целом.

Доступ к api при помощи токенов доступа

Выше мы уже немного поговорили о токенах доступа — когда рассматривали, как работает делегированный доступ с использованием OAuth 2.0 и серверов авторизации. Теперь давайте разберем все это подробнее. Для этого вернемся к нашему сценарию с HireMe123 и MyCalApp.

Заголовок jwt

Первый сегмент токена это заголовок. Он может выглядеть примерно так:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9

Заголовок токена это JSON-объект, содержащий алгоритм подписи и тип токена. Он зашифрован при помощи алгоритма base64Url (бинарные данные, представленные в виде текста).

В расшифрованном виде это выглядит примерно так:

{
  "alg": "RS256",
  "typ": "JWT"
}

Заявления

Теперь, когда мы знаем анатомию JWT, давайте остановимся на заявлениях (claims) — тех самых предложениях из сегмента полезной нагрузки токена. Как следует из самого их названия, ID-токены предоставляют идентифицирующую информацию, а содержится она в заявлениях.

Заявления аутентификации

Начнем с предложений, касающихся события аутентификации. Вот несколько примеров таких заявлений:

Заявления идентичности

Заявления также включают предложения о конечном пользователе. Вот несколько примеров таких заявлений:

Клиент: приложение

Клиентом является приложение, которое хочет осуществить доступ к аккаунту пользователя. Перед осуществлением доступа приложение должно быть авторизовано пользователем, а авторизация должна быть одобрена со стороны API.

Крипто-сегмент

Последний сегмент — это подпись или данные шифрования. JWT подписываются, чтобы их нельзя было модифицировать при пересылке. Когда сервер авторизации выпускает токен, он подписывает его при помощи ключа.

Получая ID-токен, клиент проверяет подпись (тоже при помощи ключа).

(При использовании асимметричного алгоритма для подписи и проверки используются разные ключи. В таком случае только у сервера авторизации есть возможность подписывать токены).

Не переживайте, если все это кажется запутанным. Детали того, как все работает, не должны вас беспокоить или мешать эффективно использовать сервер авторизации с аутентификацией на основе токенов.

Минусы

  • различия в подходах к реализации у разных сервисов, порождающие необходимость написания отдельного кода под каждый новый сервис;
  • если реализована интеграция с семейством приложений, работающих в одной экосистеме (например, Google), существует риск для всех интеграций при компрометации учетных данных либо сбое на стороне сервера API;
  • OAuth 2.0 является новым и динамично развивающимся протоколом, в связи с чем возможны некоторые логические противоречия в его спецификации;
  • основанная на SSL безопасность протокола может стать проблемой в высоконагруженных проектах.

Могут возникнуть проблемы с масштабируемостью

Как уже объяснялось, сервер отвечает за конфигурацию файлов cookie, и нам нужно сохранить сеансы в базе данных для каждого пользователя.

Хотя существуют хорошо
зарекомендовавшие себя способы управления масштабируемостью (например,
использование для хранения сеансов СУБД наподобие Redis), это все равно
добавляет сложности. По мере роста количества пользователей, могут возникнуть
проблемы с масштабированием и управлением сеансами.

Не подходит для api

Если вы создаете API для предоставления услуг клиентам, cookie – это не лучший вариант. Если клиент не является браузером, это усложнит работу.

Например, если вы
разрабатываете мобильное приложение, наличие файлов cookie усложнит управление
файлами по сравнению с токеном.

Образцы разделов авторизации

Ниже приведены несколько примеров разделов авторизации в документации API.

Обычно работают в одном домене

Файлы cookie работают только в одном домене, если вы специально их не настроили.

Хотя со стороны это
выглядит как ограничение, но это одна из самых сильных функций для обеспечения
единого источника.

Если ваш фронтенд
и бэкенд лежат в разных доменах или поддоменах, необходимо явно указать это
в файле cookie в белом списке. В противном случае браузер не отправит куки вместе
с запросом.

Определяем термины

Во-первых, давайте определимся с некоторыми ключевыми терминами:

  • Аутентификация: подтверждение правильности личности
  • Авторизация: разрешение определенного действия

API может аутентифицировать, но не разрешит делать определенный запрос.

аутентификация и авторизация

Подходит для хранения дополнительных данных

Поскольку этот подход поддерживает отдельные сессии для каждого пользователя, мы можем хранить прикрепленные к ним данные.

С помощью файлов cookie и
сессий можно хранить дополнительные данные персонализации, контроля доступа и сами сессии – это позволяет использовать их
для последующих запросов.

Все эти манипуляции можно провести и с помощью токенов. Например, токены JWT позволяют хранить Claim-объекты. Поскольку это увеличит размер токена, сохранение большего их количества повлияет на нагрузку сети.

Это не имеет смысла, если
речь идет об одном запросе, но преимущества становятся заметны, когда все
агрегируется и масштабируется.

Полезная нагрузка jwt

Второй сегмент токена — полезная нагрузка. Выглядеть этот сегмент может так:

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0

Это объект JSON, содержащий заявления (claims) — предложения о пользователе и событии аутентификации. Например:

Последствия нехватки безопасности api

Почему даже API-интерфейсы нуждаются в аутентификации? Для API, которые предназначены только для чтения, иногда пользователям не нужны ключи. Но большинство коммерческих API требуют авторизации в виде ключей API или других методов. Если нет никакой защиты API, пользователи могут совершать неограниченное количество запросов API без какой-либо регистрации. Разрешение неограниченных запросов усложнит модель дохода для вашего API.

Вдобавок, без аутентификации не было бы простого способа связать запросы с конкретными данными пользователя. И не было бы способа защиты от запросов от злонамеренных пользователей, которые могут удалить данные другого пользователя (например, путем удаления запросов DELETE для учетной записи другого пользователя).

Наконец, не получится отследить, кто использует API или какие конечные точки используются чаще всего. Очевидно, что разработчики API должны подумать о способах аутентификации и авторизации запросов к своим API.

В целом, аутентификация и авторизация с помощью API служат следующим целям:

Преимущества и недостатки oauth 2

Рассмотрим подробнее плюсы и минусы протокола авторизации.

Пример реализации протокола на php

Рассмотрим живой пример проекта клиент-серверного стороннего приложения, взаимодействующего по API с сервисом Google Таблицы.

Проблемы безопасности

Хотя введением токенов
пытаются решить проблемы безопасности аутентификации на основе cookies, полностью от них не избавиться.

Сохраненные в браузере токены могут быть уязвимы для атак XSS, если приложение позволяет внедрять внешние сценарии JavaScript.

Токен не имеет состояния и если он установлен снаружи, то его невозможно отозвать
до истечения срока жизни. Поэтому важно, чтобы он имел минимальный срок
годности.

Проверка согласия

Помните, мы говорили, что сервер авторизации спрашивает пользователя HireMe123, согласен ли он разрешить HireMe123 воспользоваться правами пользователя для доступа к MyCalApp?

Этот диалог выглядит примерно так:

HireMe123 может попросить предоставить ему самые разные права, на пример:

  • write:events (запись событий)
  • read:events (чтение событий)
  • read:settings (чтение настроек)
  • write:settings (запись настроек)
  • и т. д.

В целом, следует избегать давать разрешения на чисто пользовательские действия. Области видимости предназначены для прав, делегированных приложениям. Но если ваш сервер авторизации имеет функционал для контроля доступа на основе ролей (Role-Based Access Control, RBAC), вы можете устанавливать разные области видимости для разных пользователей.

При помощи RBAC на сервере авторизации можно установить разные права для разных групп пользователей. После этого сервер авторизации при выпуске токенов доступа сможет включать в scopes указание ролей пользователей.

Процесс с учётными данными клиента

Приложение запрашивает токен доступа путём отправки своих учётных данных, своего идентификатора клиента и секрета клиента авторизационному серверу. Пример POST-запроса может выглядеть следующим образом:

Различия протоколов openid и oauth 2

Основное различие между этими двумя протоколами состоит в цели использования. Так, OpenID служит для аутентификации, то есть подтверждения личности пользователя в клиентском сервисе. Например, вы можете авторизоваться в любом из сервисов Google под своим аккаунтом и работать с ними от своего имени, со своими данными.

Для верификации пользователя OpenID использует ID учетной записи у провайдера, а OAuth — авторизационные ключи (токены) с предопределенным сроком действия и правами доступа.

Разные виды авторизации

Существует несколько методов авторизации. Ниже рассмотрим несколько вариантов авторизации, которые встречаются чаще всего:

Разрешение на авторизацию

В абстрактном описании протокола выше первые четыре шага касаются вопросов создания разрешения на авторизацию и токена доступа. Тип разрешения на авторизацию зависит от используемого приложением метода запроса авторизации, а также от того, какие типы разрешения поддерживаются со стороны API. OAuth 2 определяет четыре разных типа, каждый из которых полезен в определённых ситуациях:

  • Код авторизации (Authorization Code): используется с серверными приложениями (server-side applications).
  • Неявный (Implicit): используется мобильными или веб-приложениями (приложения, работающие на устройстве пользователя).
  • Учётные данные владельца ресурса (Resource Owner Password Credentials): используются доверенными приложениями, например приложениями, которые являются частью самого сервиса.
  • Учётные данные клиента (Client Credentials): используются при доступе приложения к API.

Далее мы рассмотрим эти типы разрешения на авторизацию, примеры их использования.

Регистрация приложения

Перед тем, как начать использовать OAuth в вашем приложении, вам необходимо зарегистрировать своё приложения в сервисе. Это делается путём регистрации в разделе “developer” или “API” сайта сервиса, где вам необходимо предоставить следующую информацию (возможно, включая некоторые детали о вашем приложении):

  • Название приложения
  • Сайт приложения
  • Redirect URL или callback URL

Redirect URL – это URL, на который сервис будет перенаправлять пользователя после авторизации (или отказа в авторизации) вашего приложения.

Роли oauth

OAuth определяет четыре роли:

  • Владелец ресурса
  • Клиент
  • Сервер ресурсов
  • Авторизационный сервер

Далее мы рассмотрим каждую из ролей.

Сервер ресурсов / авторизации: api

Сервер ресурсов непосредственно хранит защищённые данные аккаунтов пользователей, а авторизационный сервер проверяет подлинность информации, предоставленной пользователем, а затем создаёт авторизационные токены для приложения, с помощью которых приложение будет осуществлять доступ к пользовательским данным.

С точки зрения разработчика приложения API сервиса одновременно выполняет и роль сервера ресурсов и роль сервера авторизации. Далее мы будем считать эти две роли одной, и называть её Сервис или API.

Тип разрешения на авторизацию: неявный

Неявный тип разрешения на авторизацию используется мобильными и веб-приложениями (приложениями, которые работают в веб-браузере), где конфиденциальность секрета клиента не может быть гарантирована. Неявный тип разрешения также основан на перенаправлении пользовательского агента, при этом токен доступа передаётся пользовательскому агенту для дальнейшей передачи приложению.

Это, в свою очередь, делает токен доступным пользователю и другим приложениям на устройстве пользователя. Также при этом типе разрешения на авторизацию не осуществляется аутентификация подлинности приложения, а сам процесс полагается на URL перенаправления (зарегистрированный ранее в сервисе).

Неявный тип разрешения на авторизацию не поддерживает токены обновления токена доступа (refresh tokens).

Процесс выглядит следующим образом: приложение просит пользователя авторизовать себя, затем сервер авторизации передаёт токен доступа к пользовательскому агенту, который передаёт токен приложению. Далее мы опишем процесс в деталях.

Тип разрешения на авторизацию: учётные данные клиента

Тип разрешения на авторизацию с использованием учётных данных клиента позволяет приложению осуществлять доступ к своему собственному аккаунту сервиса. Это может быть полезно, например, когда приложение хочет обновить собственную регистрационную информацию на сервисе или URI перенаправления, или же осуществлить доступ к другой информации, хранимой в аккаунте приложения на сервисе, через API сервиса.

Токены доступа

Токены доступа используются для предоставления доступа к ресурсам. Благодаря токену доступа, выпущенному сервером авторизации MyCalApp, HireMe123 может получить доступ к API MyCalApp.

В отличие от ID-токенов, которые OIDC определяет как JSON веб-токены, токены доступа не имеют четко определенного формата. Они не обязательно являются JWT. Тем не менее, во многих решениях для токенов доступа все же используются JWT, потому что этот формат позволяет валидацию.

Токены доступа непрозрачны для клиента

Токены доступа предназначаются для API ресурса и важно, чтобы они были непрозрачны для клиента. Почему?

Токены доступа могут измениться в любой момент. У них должно быть короткое время устаревания, чтобы пользователь мог часто получать новые. Также они могут выпускаться повторно, чтобы дать возможность доступа к другим API или с другими правами. В клиентском приложении ни в коем случае не должно быть кода, полагающегося на содержимое токена доступа. Подобный код будет слишком хрупким и практически гарантированно сломается.

Шаг 1: ссылка для неявной авторизации

При неявном типа разрешения на авторизацию пользователю предоставляется ссылка, запрашивающая токен у API. Эта ссылка выглядит почти так же, как ссылка для предыдущего способа (с кодом авторизации), за исключением того, что запрашивается токен вместо кода (обратите внимание на response type “token”):

Шаг 1: ссылка с кодом авторизации

Сначала пользователю предоставляется ссылка следующего вида:

Шаг 4: пользовательский агент следует по uri перенаправления

Пользовательский агент следует по URI перенаправления, сохраняя при этом токен доступа.

Шаг 4: приложение запрашивает токен доступа

Приложение запрашивает токен доступа у API путём отправки авторизационного кода и аутентификационной информации (включая секрет клиента) сервису. Ниже представлен пример POST-запроса для получения токена DigitalOcean:

Шаг 5: приложение выполняет скрипт извлечения токена доступа

Приложение возвращает веб-страницу, которая содержит скрипт для извлечения токен доступа из полного URI перенаправления, сохранённого пользовательским агентом.

Шаг 5: приложение получает токен доступа

Если авторизация прошла успешно, API возвращает токен доступа (а также, опционально, токен для обновления токена доступа – refresh token). Весь ответ сервера может выглядеть следующим образом:

Шаг 6: токен доступа передаётся приложению

Пользовательский агент запускает скрипт извлечения токена доступа, а затем передаёт извлечённый токен приложению.

Теперь приложение авторизовано! Оно может использовать токен для доступа к пользовательскому аккаунту через API сервиса с заданными ограничениями доступа до тех пор, пока не истечёт срок действия токена или токен не будет отозван.

Это stateless-механизм

В отличие от cookie-подхода, вариант с токенами не имеет состояния. Это означает, что он не сохраняет никакой
информации о пользователях в базе данных или на сервере. Сервер отвечает только за
создание и проверку токенов, что позволяет реализовывать более масштабируемые
решения.

👨‍💻 практическое занятие: авторизация

В своем найденном опен-сорс проекте найдем информацию об авторизации для запросов к API. Ответьте на следующие вопросы:

  • Какого рода авторизация требуется для отправки запросов к API?
  • Существуют ли разные уровни доступа в рамках авторизации (например, платные и бесплатные), которые определяют, сколько запросов можно сделать или какие типы информации можно получить?
  • Можно ли вы получить ключ API или какой-либо другой метод авторизации, необходимый для выполнения тестовых вызовов API?
  • Как информация об авторизации интегрируется в раздел “Начало работы”?

Go next ➡

Sendgrid

API ключ SendGrid

SendGrid предлагает подробное объяснение ключей API, начиная с основ, поясняя: «Что такое ключи API?». Контекстно раздел ключей API появляется вместе с другими разделами по управлению учетными записями.

Заключение

Подходы, основанные на токенах и файлах cookie – два наиболее часто используемых в веб-приложениях механизма аутентификации. В этой статье мы выяснили, как они работают, а также разобрали их особенности, плюсы и минусы.

Ни один из этих методов
не является на 100% совершенным, и каждый имеет свои недостатки. При
выборе метода аутентификации стоит использовать наиболее соответствующий требованиям проекта и допилить его, а не стремиться к идеалу.

Спасибо за внимание!

***

Дополнительные материалы:

Итоги

Мы рассмотрели очень много материала, но это даже близко не все, что можно было рассмотреть. Тем не менее, я надеюсь, что этот краткий курс по идентичности, авторизации и аутентификации будет вам полезен.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *