← Cloudflare One / cloudflare-one / access-controls / applications / http-apps / authorization-cookie
CORS
Совместное использование ресурсов между разными источниками (CORS ↗) представляет собой механизм, который с помощью заголовков HTTP предоставляет веб-приложению, работающему на одном источнике (origin), разрешение на обращение к отдельным ресурсам на другом источнике. Веб-приложение выполняет межисточниковый HTTP-запрос (cross-origin), когда запрашивает ресурс, источник которого (домен, протокол или порт) отличается от его собственного.
Чтобы CORS-запрос дошёл до сайта, защищённого Access, он должен содержать действительный CF-Authorization cookie. В зависимости от типа запроса это может потребовать дополнительной настройки:
-
Простые запросы ↗ отправляются напрямую на origin, не вызывая preflight-запрос. Инструкции по настройке см. в Разрешить простые запросы.
-
Предварительные запросы (preflight) ↗ приводят к тому, что браузер отправляет запрос OPTIONS перед фактическим запросом. Запрос OPTIONS проверяет, какие методы и заголовки разрешены источником. Инструкции по настройке приведены в Разрешить preflight-запросы.
Разрешить простые запросы
Если вы выполните простой запрос CORS к домену, защищённому Access, не выполнив предварительный вход, запрос вернёт CORS error. Устранить эту ошибку можно двумя способами:
- Вариант 1, Войдите и обновите страницу.
- Вариант 2, Создайте Cloudflare Worker, который автоматически отправляет токен аутентификации. Этот способ работает только в том случае, если оба сайта, участвующие в обмене CORS, находятся за Access.
Ручная аутентификация
- Откройте целевой домен в браузере. Откроется страница входа Access.
- Войдите в целевой домен. Это создаёт
CF-Authorizationcookie. - Обновите страницу, которая отправила CORS-запрос. При обновлении запрос отправляется повторно с новым сгенерированным файлом cookie.
Разрешить preflight-запросы
Если вы выполните предварительный (preflight) кросс-доменный запрос к домену, защищённому Access, запрос OPTIONS вернёт 403 ошибка. Эта ошибка возникает независимо от того, выполнен ли вход в домен, поскольку браузер изначально не отправляет файлы cookie с запросами OPTIONS. Поэтому Cloudflare блокирует preflight-запрос, из-за чего обмен CORS завершается сбоем.
Устранить эту ошибку можно тремя способами:
- Вариант 1, Bypass OPTIONS requests to origin.
- Вариант 2, Настройте Cloudflare для ответа на запрос OPTIONS.
- Вариант 3, Создайте Cloudflare Worker, который автоматически отправляет токен аутентификации. Этот способ работает только в том случае, если оба сайта, участвующие в обмене CORS, находятся за Access.
Bypass OPTIONS requests to origin
Вы можете настроить Cloudflare так, чтобы он отправлял запросы OPTIONS напрямую на ваш исходный сервер. Чтобы обойти Access для запросов OPTIONS:
- В Панель управления Cloudflare ↗, перейдите в Zero Trust > Контроль доступа > Приложения.
- Найдите источник, который будет получать запросы OPTIONS, и выберите Настройте.
- Перейдите в Расширенные настройки > Настройки совместного использования ресурсов между разными источниками (CORS).
- Включите Не проверять запросы OPTIONS к источнику. Это удалит все существующие настройки CORS для этого приложения.
По-прежнему важно обеспечивать соблюдение CORS для Access JWT: этот параметр следует использовать только в том случае, если применение CORS уже настроено на вашем исходном сервере.
Настройте ответ на предварительные запросы
Вы можете настроить Cloudflare так, чтобы он отвечал на запрос OPTIONS от вашего имени. Запрос OPTIONS никогда не доходит до вашего исходного сервера. После завершения предварительного обмена (preflight) браузер отправит основной запрос, который уже включает cookie аутентификации (при условии, что вы вошли в домен, защищённый Access).
Чтобы настроить, как Cloudflare обрабатывает предварительные запросы (preflight):
-
В Панель управления Cloudflare ↗, перейдите в Zero Trust > Контроль доступа > Приложения.
-
Найдите источник, который будет получать запросы OPTIONS, и выберите Настройте.
-
Перейдите в Расширенные настройки > Настройки совместного использования ресурсов между разными источниками (CORS).
-
Настройте эти Настройки CORS ↗ чтобы соответствовать заголовкам ответа, отправляемым вашим источником.
Например, если вы настроили
api.mysite.comчтобы возвращать следующие заголовки:headers: { 'Access-Control-Allow-Origin': 'https://example.com', 'Access-Control-Allow-Credentials' : true, 'Access-Control-Allow-Methods': 'GET, OPTIONS', 'Access-Control-Allow-Headers': 'office', 'Content-Type': 'application/json', }затем перейдите в
api.mysite.comв Access и настройте Access-Control-Allow-Origin, Access-Control-Allow-Credentials, Access-Control-Allow-Methods, а также Access-Control-Allow-Headers.
-
Выберите Save.
-
(Необязательно) Вы можете проверить конфигурацию, отправив запрос OPTIONS на источник с
curl. Например,curl --head --request OPTIONS https://api.mysite.com \ --header 'origin: https://example.com' \ --header 'access-control-request-method: GET'должен вернуть ответ, подобный следующему:
HTTP/2 200 date: Tue, 24 May 2022 21:51:21 GMT vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers access-control-allow-origin: https://example.com access-control-allow-methods: GET access-control-allow-credentials: true expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=A%2FbOOWJio%2B%2FjuJv5NC%2FE3%2Bo1zBl2UdjzJssw8gJLC4lE1lzIUPQKqJoLRTaVtFd21JK1d4g%2BnlEGNpx0mGtsR6jerNfr2H5mlQdO6u2RdOaJ6n%2F%2BS%2BF9%2Fa12UromVLcHsSA5Y%2Fj72tM%3D"}],"group":"cf-nel","max_age":604800} nel: {"success_fraction":0.01,"report_to":"cf-nel","max_age":604800} server: cloudflare cf-ray: 7109408e6b84efe4-EWR
Отправка токена аутентификации с помощью Cloudflare Worker
Если у вас есть два сайта, защищённых Cloudflare Access, example.com и api.mysite.com, запросы между ними будут проходить проверки CORS. Пользователи, которые входят в example.com будет выдан файл cookie для example.com. Когда браузер пользователя запрашивает api.mysite.com, Cloudflare Access ищет файл cookie, специфичный для api.mysite.com. Запрос завершится сбоем, если пользователь ещё не выполнил вход в api.mysite.com.
Чтобы не входить в систему дважды, можно создать Cloudflare Worker, который автоматически отправляет учётные данные для аутентификации в api.mysite.com.
Предварительные требования
- Аккаунт Workers
wranglerустановкаexample.comиapi.mysite.comдомены защищено с помощью Access
1. Создайте токен службы
Следуйте эти инструкции чтобы создать новый токен службы Access. Скопируйте Client ID и Client Secret в безопасное место, так как они понадобятся вам на одном из следующих шагов.
2. Добавьте политику Service Auth
-
В Панель управления Cloudflare ↗, перейдите в Zero Trust > Контроль доступа > Приложения.
-
Найдите свой
api.mysite.comприложение и выберите Настройте. -
Выберите Политики на вкладке.
-
Добавьте следующую политику:
Действие Тип правила Селектор Service Auth Включить Service Token
3. Создайте новый Worker
Откройте терминал и выполните следующую команду:
npm create cloudflare@latest -- authentication-workerЭто предложит вам установить create-cloudflare ↗ пакет и проведёт вас через процесс установки.
Для настройки выберите следующие параметры:
- Для С чего вы хотите начать?, выберите
Hello World example. - Для Какой шаблон вы хотите использовать?, выберите
Worker only. - Для Какой язык вы хотите использовать?, выберите
JavaScript. - Для Хотите использовать git для контроля версий?, выберите
Yes. - Для Хотите развернуть приложение?, выберите
No(мы внесём некоторые изменения перед развёртыванием).
Перейдите в каталог проекта.
cd authentication-workerОткройте /src/index.js и удалите существующий код, вставив на его место следующий пример:
// The hostname where your API lives
const originalAPIHostname = "api.mysite.com";
export default {
async fetch(request, env) {
// Change just the host. If the request comes in on example.com/api/name, the new URL is api.mysite.com/api/name
const url = new URL(request.url);
url.hostname = originalAPIHostname;
// If your API is located on api.mysite.com/anyname (without "api/" in the path),
// remove the "api/" part of example.com/api/name
// url.pathname = url.pathname.substring(4)
// Best practice is to always use the original request to construct the new request
// to clone all the attributes. Applying the URL also requires a constructor
// since once a Request has been constructed, its URL is immutable.
const newRequest = new Request(url.toString(), request);
newRequest.headers.set("cf-access-client-id", env.CF_ACCESS_CLIENT_ID);
newRequest.headers.set("cf-access-client-secret", env.CF_ACCESS_CLIENT_SECRET);
try {
const response = await fetch(newRequest);
// Copy over the response
const modifiedResponse = new Response(response.body, response);
// Delete the set-cookie from the response so it doesn't override existing cookies
modifiedResponse.headers.delete("set-cookie");
return modifiedResponse;
} catch (e) {
return new Response(JSON.stringify({ error: e.message }), {
status: 500,
});
}
},
};Затем разверните Worker в своей учётной записи Cloudflare:
npx wrangler deploy4. Настройте Worker
-
В Панель управления Cloudflare ↗, перейдите в Workers & Pages страницу.
Перейдите в Workers & Pages ↗ -
Выберите только что созданный Worker.
-
В Триггеры вкладке перейдите в Маршруты и добавьте
example.com/api/*. Worker размещается на подпутиexample.comчтобы избежать кросс-доменного запроса. -
В Настройки вкладке выберите Переменные.
-
В разделе Переменные окружения, добавьте следующее секретные переменные:
CF_ACCESS_CLIENT_ID=<service token Client ID>CF_ACCESS_CLIENT_SECRET=<service token Client Secret>
Client ID и Client Secret копируются из вашего токен службы.
- Включить Зашифровать для каждой переменной и выберите Save.
5. Обновите URL-адреса HTTP-запросов
Измените ваш example.com приложение отправлять все запросы на example.com/api/ вместо api.mysite.com.
Теперь HTTP-запросы должны корректно работать между двумя разными доменами, защищенными Access. Когда пользователь выполняет вход в example.com, браузер отправляет запрос к Worker вместо запроса к api.mysite.com. Worker добавляет токен службы Access в заголовки запроса, а затем перенаправляет запрос на api.mysite.com. Поскольку токен службы соответствует политике Service Auth, пользователю больше не нужно входить в api.mysite.com.
Устранение неполадок
Как правило, при устранении проблем с CORS мы рекомендуем выполнить следующие действия:
- Соберите файл HAR с описанием проблемы, а также одновременно записанный вывод консоли JS. Это связано с тем, что сам по себе файл HAR не даёт полного понимания причины проблем с cross-origin.
- Убедитесь, что приложение задало
credentials: 'same-origin'во всех запросах fetch или XHR. - Если вы используете настройка cross-origin ↗ на тегах script, для них нужно установить значение "use-credentials".