Проблема CORS в Firebase Functions: проблема с заголовком “Access-Control-Allow-Credentials” несмотря на правильную настройку.

Вопрос или проблема

Я сталкиваюсь с постоянной проблемой CORS, работая с HTTPS-функцией Firebase в своем приложении Vite.js на React, особенно при попытке интегрировать OAuth.

Проблема:
При попытке отправить запрос с моего фронтенда на функцию облака Firebase возникает следующая ошибка:callback:1 Доступ к fetch по адресу 'http://127.0.0.1:5001/my-project-id/us-central1/youtube/youtubeaccesstoken' из источника 'http://localhost:5173' был заблокирован политикой CORS: Ответ на предварительный запрос не проходит проверку контроля доступа: Значение заголовка 'Access-Control-Allow-Credentials' в ответе равно '' и должно быть 'true', когда режим проверки подлинности запроса 'include'.

Я установил credentials: ‘include’ в своем запросе fetch, и кажется, что Firebase не возвращает требуемый заголовок Access-Control-Allow-Credentials: true, даже несмотря на то, что я пытался настроить CORS как неявно, так и явно.

Что я пробовал:

  • Настройка функции Firebase: Я использовал onRequest Firebase с cors:
    true для разрешения CORS
       
           const {
             onRequest
           } = require('firebase-functions/v2/https');
       
           exports.youtube = onRequest({
             timeoutSeconds: 360,
             cors: true
           }, (req, res) => {
             // Обработка предварительного запроса OPTIONS
             if (req.method === 'OPTIONS') {
               res.set('Access-Control-Allow-Origin', 'http://localhost:5173');
               res.set('Access-Control-Allow-Methods', 'GET, POST');
               res.set('Access-Control-Allow-Headers', 'Authorization, Content-Type');
               res.set('Access-Control-Allow-Credentials', 'true');
               res.status(204).send('');
               return;
             }
       
             // Обработка фактического запроса
             res.set('Access-Control-Allow-Origin', 'http://localhost:5173');
             res.set('Access-Control-Allow-Credentials', 'true');
       
             youtubeService(req, res);
           });
       
       
  • Запрос fetch на стороне клиента: Запрос fetch на стороне клиента настроен на включение учетных данных:
fetch('http://127.0.0.1:5001/my-project-id/us-central1/youtube/youtubeaccesstoken', {
  method: 'POST',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    code,
    state,
    userId
  }),
});
  • Я также пробовал другой подход для своей функции firebase, так как я использую express.
const youtubeService = express();
youtubeService.use(express.json());
youtubeService.use(cookieParser());

const corsOptions = {
  origin: "http://localhost:5173", // Использовать конкретный источник вместо true
  methods: "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS",
  credentials: true, // Разрешить учетные данные
  allowedHeaders: ["Content-Type", "Authorization"],
};

youtubeService.use(cors(corsOptions));

//и остальные REST-эндпоинты

exports.youtube = onRequest({
    timeoutSeconds: 360,
    cors: true,
  },
  youtubeService
);

Ожидаемое поведение:
Функция Firebase должна разрешать кросс-доменные запросы, возвращая необходимые заголовки CORS, особенно Access-Control-Allow-Credentials: true, при использовании credentials: ‘include’ на фронтенде.

Вещи, которые стоит учитывать:

  • Firebase, по идее, должен неявно обрабатывать предварительный запрос, но
    я установил это явно, чтобы быть уверенным.
  • Все остальные заголовки CORS, похоже, работают нормально, кроме
    Access-Control-Allow-Credentials

.

.

Ответ или решение

Решение проблемы CORS с заголовком "Access-Control-Allow-Credentials" в Firebase Functions

Когда вы работаете с функциями Firebase в ваших приложениях, правильно настроить CORS (Cross-Origin Resource Sharing) является очень важным аспектом, особенно если вы используете аутентификацию через OAuth. В вашем случае вы столкнулись с ошибкой CORS, которая говорит о том, что заголовок Access-Control-Allow-Credentials в ответе не установлен на true, несмотря на ваши попытки правильно настроить эту функциональность.

Основная проблема

Ошибка, которую вы получаете:

Access to fetch at 'http://127.0.0.1:5001/my-project-id/us-central1/youtube/youtubeaccesstoken' from origin 'http://localhost:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.

означает, что ваша конфигурация CORS не корректно отвечает на предзапрос OPTIONS, особенно в отношении заголовка Access-Control-Allow-Credentials.

Пошаговое решение

  1. Настройка CORS для Firebase Function

Ваша текущая реализация CORS выглядит довольно близко к правильной, однако стоит убедиться, что все заголовки и методы настроены правильно. Попробуйте следующую структуру, которая включает использование cors как middleware, если вы используете Express:

const express = require('express');
const cors = require('cors');
const {
  onRequest
} = require('firebase-functions/v2/https');

const youtubeService = express();
youtubeService.use(express.json());

const corsOptions = {
  origin: "http://localhost:5173", // Укажите конкретный разрешенный источник
  methods: "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS",
  credentials: true,
  allowedHeaders: ["Content-Type", "Authorization"],
};

// Примените middleware CORS
youtubeService.use(cors(corsOptions));

// Обработка OPTIONS предзапроса
youtubeService.options('*', cors(corsOptions));

// Обработка маршрутов
youtubeService.post('/youtubeaccesstoken', (req, res) => {
  // Обработайте ваш основной запрос здесь
});

exports.youtube = onRequest({
    timeoutSeconds: 360,
}, youtubeService);
  1. Проверка клиентской части

Убедитесь, что в вашем клиентском коде действительно используется credentials: 'include' в запросах fetch. Вот пример корректной реализации:

fetch('http://127.0.0.1:5001/my-project-id/us-central1/youtube/youtubeaccesstoken', {
  method: 'POST',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    code,
    state,
    userId
  }),
});

Что учитывать

  • Если вы передаете куки или используете credentials: 'include', обязательно установите заголовок Access-Control-Allow-Credentials с значением true.
  • Убедитесь, что предзапросы OPTIONS корректно обрабатываются. В некоторых случаях нужно явно указать этот обработчик.
  • Иногда кеширование может привести к неожиданным результатам. Попробуйте использовать ctrl + F5 для принудительной перезагрузки страницы и сброса кеша.
  • Проверьте консоль разработчика в браузере на наличие других ошибок CORS и сможете ли вы просмотреть все заголовки ответа.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...