Ошибка CORS при доступе к API из JavaScript-приложения

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

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

Проблема, с которой я сталкиваюсь, возникает в основном при попытке выполнить запрос с аутентификацией через заголовки: принимаемыми заголовками всегда являются «User-Api-Key» и «User-Client-Id» вместо «Api-Key» и «Api-Username», из-за чего возникают ошибки CORS. Я не считаю, что мне нужны ключи, привязанные к пользователю. Я просто пытаюсь выполнить простой аутентифицированный запрос для создания новой темы. Если я пытаюсь использовать «User-Api-Key», получаю ошибку 403.

Ниже приведён пример кода (Angular TypeScript), но он должен быть похож на другие настройки:

    createNewTopic(postBody: any) {
        let url = "myserver.com/posts.json";
        let CATEGORY_ARTICLES = 6;
        let topicContent = `
          <p>Некоторый контент
        </p>
        <p>Сработало?</p>
        `;
        let post = {
          "title": "Tdk Test 1",
          "raw": topicContent,
          "category": CATEGORY_ARTICLES,
          "target_usernames": "tdekoekkoek",
          "archetype": "",
          "created_at": new Date()
        }
        let headers = new HttpHeaders()
          .set("Accept", "application/json")
          .set("User-Api-Key", DISCOURSE_API_KEY)
          .set("User-Key", "system")
          .set("Content-Type", "application/x-www-form-urlencoded")
        let options = {headers: headers};
        return this.http.post(url, post, options);
      }

user-api-key и user-client-id — это совершенно другой метод аутентификации. Обычные API-ключи с этими заголовками не работают. Что происходит, когда вы используете правильные имена заголовков? (api-key и api-username)

У меня возникает ошибка CORS, потому что сервер ожидает заголовок User-Api-Key. Я проверяю ожидаемые заголовки в ответе OPTIONS, и там указано именно это. На этом форуме есть похожая тема, где пользователь сталкивался с такой проблемой при вызове из JavaScript-приложения.

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

Да, именно это я и пытаюсь сделать. Это должно быть описано более четко. Это была моя стратегия с самого начала работы с Discourse. Спасибо за вашу помощь. Я борюсь с этим уже несколько дней, читая документацию. Придется переосмыслить весь подход, так как я сейчас создаю серверное приложение без серверов, хотя у меня есть доступ к серверу Node.js.

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

Если вы можете выполнить вызов API Discourse со своего сервера на Node.js, это, вероятно, будет лучшим решением. Если ваше приложение должно быть исключительно клиентским, то можно запрашивать ключи API, привязанные к пользователю, хотя их настройка значительно сложнее: User API keys specification

Честно говоря, доступ к API из клиентских приложений с включённым CORS — это крайне распространённая и стандартная практика. Не могу поверить, что нет более безопасного способа это делать. Целая индустрия строится вокруг хостинга API, к которым обращаются из разных доменов. Что касается доступа с использованием пользовательского API-ключа, я видел, как их создавать, но не до конца понимаю, какие именно учётные данные требуются. При использовании этого метода я постоянно получаю ошибку 403 — доступ запрещён.

Думаю, я оказался в схожей ситуации.

Немного о сценарии использования:

Я использую Discourse в качестве бэкенда, а фронтенд собираю на VueJS. Планирую использовать только REST API. Для каждого пользователя нашей платформы я создал пользовательский API-ключ и использую оба заголовка (Api-Key и Api-Username) для аутентификации.

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

Ничего не зашито в код жёстко: все токены получаются после корректной аутентификации.

Проблема:
Получаю ошибку CORS, хотя включил её в app.yml и настроил в разделе «Безопасность» в настройках администратора.

Ошибка: Request header field api-key is not allowed by Access-Control-Allow-Headers

Не сталкиваюсь ли я с ошибкой CORS по той же причине? Почему запросы CORS блокируются при использовании заголовков «Api-Key» и «Api-Username»? Должно быть, я неправильно понимаю сценарий их использования.

EDIT:
У меня есть гипотеза относительно моего непонимания. Когда я создаю пользовательский API-ключ через endpoint «Generate an api_key for a user» REST API, обладает ли этот ключ административными правами? Не является ли он просто пользовательским ключом для публикаций и комментариев? Если так, то ограничение становится понятным.

Поправьте меня, если я ошибаюсь.

@david разве Discourse не может просто подписывать секрет сессии на сервере с помощью HMAC, а затем использовать этот секрет сессии для подписи данных в рамках данной сессии? Если его украдут, то, предположительно, это не затронет cookie сессии или CSRF-токен. Это немного похоже на цепочку сертификатов — вам не нужно помещать корневой ключ в браузер.

Это относится только к административному API. Как я понял, для JavaScript-клиентов необходимо, как упоминалось выше, ознакомиться со спецификацией: User API keys specification.