Подтвердить что ты не робот

Архивирование ключей API и токенов доступа

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

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

  • Пользователь регистрируется в интерфейсе с использованием OAuth2 (предоставление пароля) и получает токен доступа. Этот токен используется для аутентификации пользователя. Таким образом, пользовательский интерфейс, который сам использует API, может извлекать данные и отображать их.

  • Я также хочу, чтобы у пользователя был ключ API для выполнения одних и тех же вызовов, но в его приложении. Очевидно, что, вопреки токену доступа, я хочу, чтобы ключ API был долговечным. Кроме того, вопреки токена доступа, привязанного к данному пользователю (если мы вводим командный механизм, каждый пользователь будет иметь различный токен доступа, хотя они имеют доступ к тем же ресурсам), ключ API должен быть уникальным для проекта.

В то время как похоже, я не уверен, как это сделать. Я думаю, что внутри, как ключи API, так и токены доступа должны храниться в одной таблице, но ключи API не имеют времени истечения. Я прав?

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

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

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

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

Звучит ли это здорово? Кто-нибудь уже реализовал такую ​​вещь?

Спасибо!

4b9b3361

Ответ 1

Я думаю, вы не должны считать "ключи API" заменой токена доступа.

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

Поток, который я лично реализую, следующий:

  • Пользователь аутентифицируется с типом предоставления пароля с общим клиентом для каждого пользователя (т.е. клиент вашего веб-приложения, который является общедоступным, т.е. не имеет client_secret).
  • Затем пользователь может создать свой собственный клиент. Согласно спецификациям OAuth2, они не являются общедоступными, поэтому они состоят из client_id и a client_secret. Это то, что вы называете "API-ключами".
  • Затем пользователь сможет запросить токен доступа через своего клиента с любым типом гранта, который вы хотите поддержать (например, прямые учетные данные клиента, код авторизации, неявные, третьи стороны и т.д.). Вам нужно будет немного рассказать о надлежащих методах обеспечения безопасности при работе с учетными данными клиента.

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

Затем вы сможете определить токены TTL или их отсутствие в каждом клиенте или на основе типа гранта (например, токен доступа, запрошенный с помощью пароля, только для использования клиентом веб-приложения, будет иметь короткий TTL, тогда как авторизация код предоставит долгоживущие токены).
Однако я бы посоветовал полностью отказаться от ТТЛ и, скорее, использовать тип гранта refresh_token для обновления токенов доступа с истекшим сроком действия.

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

Итак, чтобы подвести итог, вот соотношения:

Пользователь имеет Клиент.
Клиент имеет Пользователь.
Клиент имеет много токенов.
Токен имеет Клиент.
Токен имеет Пользователь.

YMMV на двунаправленных направлениях.

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

TL; DR: "Ключи API" на самом деле являются клиентами OAuth2 .

Ответ 2

Спасибо за ваш ответ.

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

Вопрос: как приложение может узнать, является ли это токеном доступа или ключами API. Я имею в виду, хорошо, скажем, что в моей базе данных каждый пользователь имеет столбец "api_key" в своей базе данных.

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

Случай 1: мои собственные веб-приложения выполняют вызовы API

Работа выполняется следующим образом, используя OAuth2:

  • Пользователь вводит свой пароль/пароль.
  • Сервер авторизации возвращает токен доступа (например: "abc" ).
  • В веб-приложении все вызовы API выполняются с использованием этого токена. Например: "/payments/1" с заголовком авторизации: "Bearer abc".

Приятный и простой.

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

Очевидно, что механизм авторизации должен оставаться неизменным. Итак:

  • Пользователь переходит в свой аккаунт и читает, что его ключ API "def".
  • В своем серверном коде они могут выполнять один и тот же вызов с тем же механизмом аутентификации. Таким образом, он может называть "/payments/1" авторизацией: "Определение несущей".

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

Одна потенциальная идея, которую я использовал, - это использовать другой механизм auth. Для OAuth это будет "Authorization: Bearer accessToken", тогда как для API это будет обычная проверка подлинности: "Авторизация: базовый apiKey".

Звучит ли это хорошо?

Ответ 3

Я написал сообщение о том, как использовать токены доступа для приложений RESTful: https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/. Возможно, это может дать некоторые намеки.

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

Насколько я понимаю, у вас есть два типа пользователей ваших приложений:

  • Конечные пользователи, использующие веб-интерфейс (логин с паролем через OAuth2)
  • Приложения (вход с ключами API)

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

Кроме того, я думаю, что этот ответ может дать вам несколько других советов: Защита моего REST API с помощью OAuth, но все же позволяющая аутентификацию через сторонних поставщиков OAuth (используя DotNetOpenAuth).

Надеюсь, он ответит на ваш вопрос. Thierry