Гибкая авторизация для всех!

Аудитория

Эта статья предназначена для тех, кто ищет обзор проекта основного протокола IETF GNAP.

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

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

Это означает, что вам потребуется довольно глубокое понимание OAuth2.0, к счастью, это можно почерпнуть из отличной статьи здесь. Мы также будем ссылаться на некоторые из его расширений, но не будем называть их отдельными объектами.

Почему ГНАП?

GNAP был введен для решения тех же проблем, что и OAuth2.0 и OIDC, и делает это аналогичным образом. Он по-прежнему запрашивает делегированную авторизацию у владельца ресурса через грант и по-прежнему использует сервер авторизации.

Я сразу слышу, как вы спрашиваете: Зачем нам это тогда?, что невероятно справедливо. Однако GNAP решает некоторые важные проблемы, которые мы рассмотрим далее.

Гибкость согласия и авторизации

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

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

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

Регистрация намерений и согласование в реальном времени

В зависимости от типа гранта OAuth2.0, который мы используем, мы, как правило, начинаем с разных мест, и следующие шаги жестко определены. GNAP, с другой стороны, всегда начинается в одном и том же месте (о чем мы расскажем в разделе «запрос доступа»).

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

Клиентские экземпляры

В OAuth2.0 мы требуем, чтобы клиент был зарегистрирован и имел идентификатор клиента. GNAP стремится устранить это требование. Это описано в разделе Идентификация экземпляра клиента.

Расширенное делегирование

OAuth2.0 полагается на области, чтобы решить, какой доступ нам нужен, которые часто используются неправильно. В GNAP есть несколько более сложный метод принятия решения о том, какую авторизацию вы можете делегировать. Это описано в разделе «Права доступа к ресурсам».

Безопасность на основе криптографии

В GNAP у клиента есть ключ, и связь привязана к нему. Мы рассмотрим это в разделе «Идентификация экземпляра клиента».

Конфиденциальность и полезная безопасность

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

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

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

Хорошо, давайте погрузимся!

Основные роли в GNAP

Как и в OAuth2.0, существует ряд основных ролей, которые нам необходимо понять, чтобы оценить GNAP.

  • Конечный пользователь: лицо, желающее получить доступ к защищенным ресурсам.
  • Сервер авторизации: отвечает за предоставление привилегий (путем выдачи маркеров доступа или иным образом) и предоставляет URI конечной точки предоставления (точка входа для GNAP). В OAuth2.0 у нас есть токен и конечные точки авторизации, что позволяет нам начинать предоставление и получать токены.
  • Владелец ресурса. Объект с защищенным ресурсом, к которому он может предоставить доступ. Например, пользователь (владелец ресурса) с адресом электронной почты (его ресурсом), хранящимся на сервере ресурсов, чтобы он мог предоставить доступ к своему адресу электронной почты приложению.
  • Сервер ресурсов:сервер, на котором хранится ресурс владельца ресурса. Требуется действительный токен доступа с запросами на защищенные ресурсы.
  • Клиент. Это то, как конечный пользователь взаимодействует с сервером авторизации и сервером ресурсов. GNAP различает клиентское программное обеспечение и клиентские экземпляры. Ваше приложение может считаться клиентским программным обеспечением, и единственным случаем его работы на машине (скажем, конкретной установки, работающей на конкретном устройстве) будет экземпляр клиента. Экземпляры клиента могут иметь уникальные идентификаторы, которые отличаются от OAuth2.0, где каждый из них будет иметь один и тот же идентификатор клиента.

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

Теперь нам нужно определить некоторые элементы

Элементы в GNAP

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

  • Тема: человек, организация или устройство.
  • Информация о субъекте:информация, предоставленная сервером авторизации по субъекту. Это могут быть такие вещи, как токен идентификатора OIDC.
  • Атрибут. Это характеристики субъекта. Субъект отвечает за принятие решения о том, кому и как разрешен доступ к его атрибутам.
    Не буду врать, мне было немного сложно найти разницу между атрибутом и информацией о предмете. Я думаю, что атрибуты — это просто более общие свойства субъекта (что это за устройство и т. д.), тогда как информация о предмете более строго определена.
  • Правильно: способность субъекта выполнять данную операцию на данном защищенном ресурсе.
  • Токен доступа. Как и в OAuth2.0, он представляет собой набор прав. В GNAP это также может представлять атрибуты.
  • Защищенный ресурс: конечная точка, предоставляемая сервером ресурсов, доступ к которой возможен только с помощью действительного токена доступа.
  • Предоставление: разрешение (и определение условий) получения клиентом атрибутов или делегированных разрешений авторизации.
  • Привилегии: право или атрибут, связанные с субъектом. Аналогично областям в OAuth2.0

Поток протокола

Одним из мотивов GNAP было обеспечение более высокого уровня гибкости, чем OAuth2.0. Мы всегда начинаем с одного и того же места, и поток развивается оттуда. Это совершенно отдельно от OAuth2.0, где в зависимости от гранта, выбранного в начале, мы точно знаем, какие шаги мы предпримем.

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

Сущность, которая перемещается между состояниями, является запросом на предоставление (определено ранее). Например, мы говорим, что запрос на грант обрабатывается, затем запрос на грант находится на рассмотрении и т. д.

Пройдемся по каждому состоянию.

Обработка

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

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

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

В ожидании

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

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

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

Если истекает время ожидания всех запросов на взаимодействие или клиент отзывает запрос на доступ, то он переходит в завершенное состояние.

Одобрено

Ура! Теперь вы можете получить свои ресурсы! Сервер авторизации может передавать токены доступа и информацию о субъекте.

Возможно, мы разрешаем обновления запроса с одобренного этапа. Мы также можем запросить новые токены доступа, отправив запрос на продолжение опроса или используя API управления токенами.

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

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

Завершено

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

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

Использование GNAP

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

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

Общая последовательность протокола

Если вы знакомы с OAuth2.0, это можно сравнить с потоком протокола, определенным в начале RFC. Здесь мы определяем общую форму того, что происходит, а затем расширяем ее более подробно позже.

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

Взаимодействия

Взаимодействия — это способ сказать: «Кто-то должен что-то сделать, чтобы этот грант был одобрен». Они бывают разных форм. Мы расширим предыдущий протокол, чтобы продемонстрировать некоторые из них.

Взаимодействие на основе перенаправления

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

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

Мы могли бы использовать это в ситуациях, аналогичных коду авторизации с потоком PKCE из OAuth2.0.

Взаимодействие пользователя с кодом

Для тех из вас, кто знаком с предоставлением авторизации устройства в OAuth2.0, это должно быть достаточно просто! Это позволяет нам выдавать токены доступа на любое устройство, которое может отображать код пользователя.

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

Асинхронное взаимодействие авторизации

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

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

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

Авторизация только программного обеспечения

Это GNAP-эквивалент предоставления учетных данных клиента OAuth2.0, и он почти настолько прост, что не выдерживает обсуждения! Обзор гранта ниже.

Обновление маркера доступа с истекшим сроком действия

Основная обязанность GNAP — выдача токена доступа. Однако для обеспечения безопасности в случае кражи они должны истечь. Это означает, что нам нужен способ получить новый (обновление токена). Существует эквивалент OAuth2.0 с использованием токенов обновления, однако с GNAP мы больше не используем отдельные учетные данные обновления.

Запрос только информации о субъекте

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

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

Межпользовательская аутентификация

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

Требования для использования этого потока:

  • Экземпляр клиента должен иметь возможность получать запросы от сервера авторизации.
  • Конечный пользователь должен пройти предварительную аутентификацию в экземпляре клиента.

Это позволяет конечному пользователю получать доступ к информации владельца ресурса от его имени.

Запрос доступа

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

Изначально мы можем запросить две вещи: токены доступа (множественное число важно, это отличается от OAuth2.0, где мы запрашиваем только один) и/или информацию о теме.

Если мы запрашиваем токены доступа, нам нужно определить права (к чему токен доступа предоставляет нам доступ, области действия на языке OAuth2.0 и описаны в разделе права доступа к ресурсам). Мы также можем указать, хотим ли мы, чтобы возвращаемый токен был привязан к нашему клиентскому ключу (описанному в разделе Идентификация экземпляра клиента) или к токену-носителю.

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

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

Эта точка входа эквивалентна началу диаграммы состояний, которую мы продемонстрировали ранее. Он отвечает за создание запроса на предоставление и перевод его в состояние обработки.

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

Запрос информации о предмете

Запрос информации о субъекте (т.е. информации о владельце ресурса) немного отличается. Клиент отправляет поля, объявляющие:

  1. Идентификатор темы: как мы идентифицируем владельца ресурса, о котором нам нужна информация о теме.
  2. Форматы идентификатора темы. Учитывая, что мы получили владельца ресурса по его идентификатору темы, мы хотим получить эти другие идентификаторы для той же темы.
  3. Форматы утверждений: массив запрошенных форматов утверждений (ссылка на статью), например. Идентификационные токены или утверждения SAML 2.

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

Взаимодействие с Пользователем

Одним из основных свойств GNAP является функциональность взаимодействия. Часто мы хотим использовать это для взаимодействия с владельцем ресурса для утверждения доступа к ресурсам.

Мы сообщаем о взаимодействиях, используя три поля:

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

1. Завершить: как мы можем завершить взаимодействие.

1. Подсказки: они немного сообщают серверу авторизации о взаимодействии. Например, какую локаль использовать.

Лично я нахожу концепцию начала, окончания, продолжения немного сложной для понимания. Немного проще понять, используя поток на основе перенаправления. В этом конкретном примере началом будет «перенаправление», демонстрирующее потоки, которые мы можем использовать. Концом будет URI экземпляра клиента, который сервер авторизации может использовать, когда владелец ресурса завершит свое взаимодействие.

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

Предоставление (запрос на доступ) Ответ

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

  1. Информация о продолжении: здесь клиент может отправлять запросы на продолжение авторизации. Например, в потоке на основе перенаправления сервер авторизации сообщает экземпляру клиента, где он может продолжить поток после того, как он выполнил аутентификацию и авторизацию конечного пользователя. Больше полезной информации о продолжении — здесь.
  2. Взаимодействие: экземпляр клиента может указать, какой тип взаимодействия он поддерживает (например, перенаправление для запуска потока на основе перенаправления). Если сервер авторизации поддерживает эти режимы взаимодействия, то он возвращает необходимую для этого информацию. Еще немного полезной информации о взаимодействиях — здесь.
  3. Токены доступа: токены доступа, если сервер авторизации сочтет, что клиент их заслуживает.
  4. Информация о теме: это информация о владельце ресурса, которую мог запросить клиент.
  5. Идентификатор экземпляра: идентификатор, который клиент может использовать в будущих запросах к серверу авторизации.
  6. Ошибка: как мы сообщаем клиенту, что что-то пошло не так.

API управления токенами

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

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

Это также описано в разделе «Обновление токена доступа с истекшим сроком действия».

Отзыв токена делает именно то, что написано на банке, и отменяет существующий токен.

Идентификация экземпляра клиента

Ранее мы говорили о том, как GNAP перешла от необходимости регистрации клиентов к более гибкой модели. Информация о клиенте отправляется вместе с первоначальным запросом на создание гранта, а не отдельно.

Две основные группы передаваемой информации:

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

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

Это создает проблемы в том, что если кто-то украдет токен, он может использовать его как угодно! Для борьбы с этим существует так называемое демонстрируемое доказательство владения (DPoP), которое помогает привязать токены к паре открытого/закрытого ключа, которой владеет клиент, предотвращая злоупотребление украденными токенами.

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

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

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

Этот процесс подписи также применяется к токенам доступа. Если мы начали предоставление с ключа, все запросы, использующие токен доступа, должны содержать соответствующую подпись, если только мы специально не запросили токен носителя. Не слишком отличается от DPoP!

Права доступа к ресурсам

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

Это выражается в виде массива JSON, содержащего следующие рекомендуемые свойства:

  • Действия: например, чтение или запись.
  • Местоположения. Расположение (например, URI) серверов ресурсов, к которым мы хотели бы получить доступ.
  • Типы данных. Это могут быть такие вещи, как «метаданные» или «файлы».
  • Идентификатор:конкретные идентификаторы ресурсов на сервере ресурсов.
  • Привилегии: администратор, например.

Или как однострочное сопоставление с набором вышеуказанных свойств, о которых сервер авторизации уже знает.

"access": [
    {
        "type": "file-api",
        "actions": [
            "read"
        ],
        "locations": [
            "https://app.example.com/"
        ],
        "datatypes": [
            "metadata",
            "files"
        ],
        "privileges": [
            "user"
        ]
    },
    "write"
]

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

Открытие

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

Одна интересная особенность GNAP — это способность сервера ресурсов сообщать клиенту, у которого отсутствует действительный токен доступа, местонахождение сервера авторизации.

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

Поскольку GNAP предоставляет только одну конечную точку, нет необходимости в расширенных метаданных сервера авторизации, как в OAuth2.0.

Доверительные отношения и модель доверия

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

Заключение

В заключение, мы рассмотрели Протокол переговоров о гранте и авторизации на очень высоком уровне. В частности, чем он отличается от OAuth2.0. Надеюсь, это было полезно!