User API keys specification

Мне кажется, что значение по умолчанию для allowed_user_api_auth_redirects — «discourse://auth_redirect» — слишком ограничительное, особенно учитывая, что «discourse» не выглядит валидным URI-схемой.

Пожалуйста, объясните логику, стоящую за этим значением по умолчанию. Спасибо.

У меня тоже возникла эта проблема. Если я инициирую API из JS-приложения, то автоматически разрешёнными заголовками становятся User-Api-Key и User-Api-Client-Id, хотя мне не нужны ключи API пользователя. Всё, что мне нужно, — это простой ключ API, но ничего не работает. Если я пытаюсь передать Api-Key в заголовках, получаю ошибку CORS, так как система ожидает User-Api-Key. Но когда я пытаюсь использовать User-Api-Key, получаю ошибки 403. Я зашёл в тупик. Мне кажется, это базовый сценарий использования API. Я не пытаюсь делать ничего необычного. Я просто хочу создать новую тему в посте.

2 лайка

Это пользовательская схема URI, используемая приложением DiscourseHub для iOS и Android.

6 лайков

У меня есть вопрос касательно «токенов на чтение» и «токенов на запись». Этот комментарий датирован 2016 годом, так что, возможно, ситуация уже изменилась? Или настройки по-прежнему по умолчанию ограничиваются только «токенами на чтение»?

Контекст: я один из разработчиков распределённой системы социальных сетей. У нас уже есть коннекторы к нефедеративным системам. Идея состоит в том, чтобы также написать дополнение для Discourse. Но поскольку, скорее всего, большинство систем не позволят пользователям генерировать токены, разрешающие публикацию, мы попробуем другой подход. У нас уже есть почтовый коннектор. Тогда мы просто воспользуемся функцией рассылки в Discourse, попробуем улучшить возвращаемое содержимое и будем публиковать сообщения через SMTP.

Вы можете записывать токены, если сразу запросите соответствующую область доступа

3 лайка

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

Поэтому, возможно, сначала я сосредоточусь на интеграции писем из режима рассылки. Или есть возможность совместить эти два подхода? Имеется в виду: чтение постов через API, но отправка писем через SMTP?

Привет… Я не знаю, как сгенерировать public_key. Нужно ли мне использовать генератор RSA для получения пары открытых/закрытых ключей?
Если да, то я использовал несколько онлайн-генераторов RSA, но получаю эту ошибку:

OpenSSL::PKey::RSAError (Ни открытый, ни закрытый ключ: вложенная ошибка asn1) /var/www/discourse/app/controllers/user_api_keys_controller.rb:189:in `initialize'

Также хочу спросить вас: подходит ли это для моего случая?
У меня есть приложение, и я хочу в основном аутентифицировать пользователя и получить его имя. Является ли процесс генерации API-ключа самым простым способом для проверки входа пользователя в моём приложении? Если возможно, я хочу избежать SSO, так как он кажется более сложным.

У меня та же ситуация, хотя я пытаюсь использовать только User-Api-Key (а не Api-Key) для создания темы и получаю отказ CSRF из библиотеки actionpack.

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

@sam Как ты смотришь на то, чтобы разрешить передачу ключей API пользователей, у которых есть только область read, через параметры URL в запросах GET?

Сценарий использования: интеграции, такие как подписка на улучшенные закладки с напоминаниями в Google Calendar с помощью ключей API пользователей.

5 лайков

Как насчет создания новой конкретной области видимости с третьим параметром, указывающим «разрешен GET-параметр»? Таким образом, люди не смогут злоупотреблять ею для других целей (например, обхода CORS и запроса API Discourse с другого сайта).

(отсюда)

SCOPES = {
    read: [:get],
    write: [:get, :post, :patch, :put, :delete],
    message_bus: [[:post, 'message_bus']],
    push: nil,
    one_time_password: nil,
    notifications: [[:post, 'message_bus'], [:get, 'notifications#index'], [:put, 'notifications#mark_read']],
    session_info: [
      [:get, 'session#current'],
      [:get, 'users#topic_tracking_state'],
      [:get, 'list#unread'],
      [:get, 'list#new'],
      [:get, 'list#latest']
    ],
+   calendar: [ [:get, 'users#bookmarks_cal', true ] ],
  }

(Кстати, почему мы здесь используем вложенные массивы…)

10 лайков

Мне нравится, что API-ключ явно помечается как «разрешённый в GET» на уровне пользователя.

В целом эта опция может быть открыта для любых GET-запросов. Правило, которое мне нравится, при работе в этом режиме:

  1. API-ключ пользователя на 100% ограничен одним конкретным действием контроллера GET.
  2. API-ключ пользователя помечается как разрешённый в параметрах запроса GET.

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

Думаю, {get: 'list#new'}, {get: 'list#latest'} тоже сработает.

7 лайков

Меня очень интересует тип ключей API для пользователей «только get-параметр». Скажите, планируете ли вы разрешить пользователям создавать такие ключи через интерфейс?

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

4 лайка

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

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

В частности, я не уверен, как выполнить всю генерацию открытого/закрытого ключа.

Можно ли просто использовать OAuth 2 с Discourse в качестве провайдера OAuth?

2 лайка

Вам удалось сделать это с помощью User-Api-Key? У меня тоже возникает ошибка «У вас нет прав для просмотра запрошенного ресурса».

1 лайк

Я понял, в чём была моя ошибка: возвращаемая полезная нагрузка — это не сам ключ UserAPI, а зашифрованная строка JSON, которую необходимо расшифровать с помощью закрытого ключа из пары закрытый/открытый ключи.

2 лайка

РЕДАКТИРОВАНО: Мне удалось заставить большую часть работать, и я предоставлю описание, когда всё будет полностью готово.


Как клиент получает пару ключей (приватный/публичный) и идентификатор?

Можете ли вы предоставить код для получения ключа пользовательского API в JavaScript-приложении? (JavaScript-приложение, пытающееся разрешить пользователю делать вызовы API к форуму Discourse).

Я получаю ошибки 403. Или ошибку: Извините, мы не можем выдать ключи пользовательского API, эта функция может быть отключена администратором сайта (хотя на моём сайте включено: Разрешить генерацию ключей пользовательского API).

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

Любой код будет очень полезен.

Мне удалось заставить это работать после некоторых проб и ошибок.

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

Для этого мне нужно генерировать API-токен для каждого пользователя, чтобы выполнять вызовы от имени конкретного пользователя (по крайней мере, в среде Node.js/JavaScript).


Обратите внимание, что для JavaScript-части я нашел код, предоставленный @KengoTODA здесь: discourse-api-key-generator/src/index.ts at main · KengoTODA/discourse-api-key-generator · GitHub, очень полезным.


Вот шаги, которые я выполнил:

Первый шаг: Сгенерировать пару публичного и приватного ключей.

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

Второй шаг: Настроить URL перенаправления.

Это URL, на который Discourse будет перенаправлять, передавая финальный API-токен в полезной нагрузке (payload). Если у вас десктопное приложение (то есть без URL в браузере), URL перенаправления будет основан на пользовательском протоколе, который вы настроили и который открывает приложение при вводе URL перенаправления в браузере.

Обратите внимание, что URL перенаправления должен быть добавлен в белый список в настройках сайта целевого сайта Discourse.

Также, скорее всего, в настройках сайта Discourse должен быть включен параметр «Разрешить API-ключи пользователей». См. оригинальный пост по этой теме в разделе «Настройки сайта».

Третий шаг: Отправить вызов API-запроса на URL запроса Discourse.

Итак, ваше приложение отправит вызов на URL, который имеет следующий вид:

https://[ваш целевой сайт discourse .com]/user-api-key-new"

и добавляет следующие параметры:

  • имя вашего приложения
  • ваш “client_id” (мне удалось использовать hostname() из const {hostname} = require('os') для десктопного приложения, точно так же, как в упомянутом выше гисте на GitHub)
  • scopes (это те права доступа, которые вы хотите предоставить пользователю через API, например, “write”, “read” и т. д.)
  • ваш публичный ключ (из шага 1 выше)
  • ваш URL перенаправления (из шага 2 выше)
  • nonce (это значение, которое вы можете выбрать — например, использование ‘1’ кажется работающим)

Четвертый шаг: Пользователь авторизует ваше приложение на странице сайта Discourse, которая открывается по URL запроса.

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

На этой странице есть кнопка, которую пользователь должен нажать, чтобы разрешить доступ. Когда пользователь нажимает эту кнопку, сайт Discourse перенаправляет на указанный вами URL перенаправления и добавляет параметр ?payload=[API-КЛЮЧ]. Здесь API-КЛЮЧ — это ключ, который вам нужно декодировать в вашем приложении.

Пятый шаг: Ваше приложение перехватывает значение URL перенаправления (с полезной нагрузкой), и вы декодируете API-КЛЮЧ.

Вы почти у цели. Ваше приложение должно проанализировать URL перенаправления, на который перенаправил Discourse, и извлечь API-ключ, содержащийся в полезной нагрузке.

Как только у вас есть этот API-ключ, вам нужно сделать две вещи:

  1. Получить сам ключ, а не URL-кодированную версию: если вы получаете параметр из URL, он часто бывает URL-кодированным (добавляются % и т. д.). Вам нужно его очистить. В JavaScript я обнаружил, что decodeURIComponent отлично подходит для этого.
  2. Как только вы получите очищенный API-КЛЮЧ, возвращенный Discourse, вам нужно его декодировать. Для этого можно использовать декодирование в JavaScript с помощью приватного ключа. По сути, вы используете свой приватный ключ (сгенерированный на первом шаге выше) для декодирования очищенного API-КЛЮЧ. В гисте на GitHub, на который я ссылался выше, есть пример кода на JavaScript: discourse-api-key-generator/src/index.ts at main · KengoTODA/discourse-api-key-generator · GitHub

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

Шестой шаг: Используйте токен (то есть финальный, очищенный, декодированный API-КЛЮЧ) для выполнения API-вызовов от имени пользователя.

С этим токеном, похоже, вам не нужно указывать имя пользователя в API-вызове. Я считаю, что следующего заголовка достаточно при включении его в ваши вызовы GET, POST, PUT и т. д.:

headers: {
"User-Api-Key": [токен]
}

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

7 лайков

Какие последствия для безопасности влечёт добавление элементов в allowed_user_api_auth_redirects? У меня есть запрос от кого-то на добавление строки для поддержки интеграции с NextCloud.

1 лайк