Аутентификация с помощью Passport + Facebook + Express + create-react-app + React-Router + proxy
TL;DR: Как мне инициировать процесс аутентификации Facebook со страницы в приложении React?
Я нашел немало сообщений, которые касаются большинства, но не всех, элементов, которые я перечислял в заголовке этого сообщения. И я довольно близка к тому, чтобы это работало, но, должно быть, кое-что мне не хватает.
Мое приложение состоит из front-end-приложения-приложения-приложения, использующего маршрутизатор-ответ для маршрутизации. У меня это работает на порту 51000 в моей среде разработки. В package.json я использую "прокси" для перенаправления других маршрутов на мой экспресс-сервер, работающий на порту 51001. Это работает в целом для запросов в моих компонентах React, которые попадают на сервер. Например:
axios.get('/api/some-stuff')
При вызове в моем компоненте React это успешно ударит мой сервер Express.
Я хочу, чтобы мои внутренние маршруты были аутентифицированы, и я решил использовать Facebook auth через паспорт-facebook. Я установил это так же, как и многие онлайн-обучающие программы, которые я видел. Например, у меня есть маршрут на моем экспресс-сервере с именем '/auth/facebook'. Если я перейду на localhost: 51001/auth/facebook, он перенаправляет меня на facebook для входа в систему, а затем перенаправляет меня обратно на какой-то маршрут, который я ему дал. Таким образом, поток работает так, как ожидалось.
Конкретная проблема, с которой я столкнулась, - это заставить React успешно инициировать и завершить вызов api, запускающий auth. Я пробовал два подхода.
Подход 1: вызов маршрута через ajax
В своем компоненте componentDidMount я назвал следующее:
axios.get('/auth/facebook')
Это успешно удаляет мой экспресс-сервер, но затем немедленно генерирует следующую ошибку в консоли браузера:
XMLHttpRequest не может загрузить https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http%... 2Flocalhost% 3A51000% 2Fauth% 2Ffacebook% 2Fcallback & client_id = XYZ. Перенаправление из " https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http%... 2Flocalhost% 3A51000% 2Fauth% 2Ffacebook% 2Fcallback & client_id = XYZ в https://www.facebook.com/login.php? skip_api_login = 1 & api_key = XYZ... _ & display = page & locale = en_US & logger_id = 7f30b5a1-2ad1-dc31-f08b-70d3cfdd55fa 'заблокирован политикой CORS: заголовок "Access-Control-Allow-Origin" присутствует на запрошенном ресурсе. Происхождение ' http://localhost: 51000 ', следовательно, не допускается.
** Подход 2: Переход к маршруту в браузере **
Другое, что я пробовал, что я видел во всех учебниках, - это добавить ссылку на одну из моих страниц, которая просто переходит на маршрут аутентификации. Например:
<a href="/auth/facebook">Login with Facebook</a>
Однако, когда я нажимаю на это, я просто заканчиваю на http://localhost: 51000/auth/facebook или просто пустую страницу в моем приложении React. Прокси-сервер, который у меня есть, не срабатывает, и я не вижу никаких действий на моем Экспресс-сервере, когда я иду на этот маршрут в браузере, хотя это не Маршрут, который я определил в ответ-маршрутизаторе.
Поэтому я немного застрял здесь. Должен ли щелчок на этом теге инициировать запуск этого маршрута против моего экспресс-сервера? Есть ли способ сказать реактивному маршрутизатору игнорировать определенные маршруты, чтобы они перенаправлялись на мой экспресс-сервер? Это работает нормально при выполнении вызовов AJAX, но если я перейду на localhost: 51000/not/a/route, это не приведет к перенаправлению запроса на Express. Он просто загружает страницу реакции без содержимого.
Любая помощь приветствуется.
Спасибо,
-Dan
РЕДАКТИРОВАТЬ
Поэтому я вроде как сейчас работаю, хотя я вовсе не уверен, что это "правильный" способ сделать что-то.
В моем приложении для реагирования (напомним, что он работает на порту 51000), у меня есть следующая ссылка:
<a href="#" onclick="location.href='http://localhost:51001/auth/facebook'; return false;">Facebook Login</a>
Обратите внимание, что это указывает прямо на мой сервер API, а не на ответный маршрут. Навигация по этой ссылке попадает на экспресс-сервер и сразу же перенаправляется на Facebook. Вход в систему перенаправляется обратно на мой экспресс-обратный вызов facebook, который сам перенаправляет на http://localhost: 51000/somePage, который теперь возвращается в мое приложение-ответ.
В идеале этот тег будет идти в /api/auth/facebook, вместо жесткого кодирования, чтобы перейти на другой URL/порт. Я обновлю эту проблему, если/когда я выясню, как получить ответ-маршрутизатор, чтобы передать это, вместо того, чтобы рассматривать его как страницу, которую нужно загрузить.
EDIT 2
Я открыт для того, чтобы кто-то говорил мне об этом, но я думаю, что мой нынешний подход на самом деле очень хорош. Я подумал, как все будет вести себя на производстве. Я отвечу на сайт www.example.com, с моим экспресс-сервером, доступным через api.example.com. Моя ссылка на вход в Facebook будет на "api.example.com/auth/facebook". Обратный вызов, предполагающий успешный аут, будет перенаправлен на "www.example.com/some/route". Я думаю, что разумно подпрыгнуть к URL-адресу "api", чтобы выполнить вход в систему. В конечном счете, нет смысла пытаться заставить реактор-маршрутизатор игнорировать определенные маршруты, так как все мои вызовы api будут направлены на явный маршрут.
Я понимаю, что я не предлагаю полное полезное решение для других. После того, как у меня будет все это, я включу ссылку на мое репо, содержащее этот поток входа, если кто-то найдет его полезным.
** РЕДАКТИРОВАТЬ 3 **
Вот ссылки на мой проект. Не будет тривиально, чтобы весь проект работал, но есть только несколько файлов, связанных с потоком auth.
Вы можете просмотреть репо здесь: https://github.com/dan-goyette/Portfolio
Маршрутизатор Express для этого здесь:
https://github.com/dan-goyette/Portfolio/blob/master/portfolio-server/src/Routing/auth.js
В пользовательском интерфейсе я запускаю вызовы на экспресс-сервер, используя этот компонент:
https://github.com/dan-goyette/Portfolio/blob/75ca9326e6227d0601cdfa4c0cece672bd347302/portfolio-ui/src/Components/SocialMenuButton/SocialMenuButton.js
Вы можете увидеть, как он работает на странице https://www.dan-goyette.com/home, в верхней правой части.
Ответы
Ответ 1
Я также столкнулся с этой проблемой - изменение конфигурации прокси-сервера CRA показало, что это трюк:
"proxy": {
"/api": {
"target": "http://localhost:3001/"
}
}
Если ссылка OAuth находится в /api/auth/foo
, приложение CRA находится на localhost:3000
, а экспресс-приложение - на localhost:3001
Ответ 2
Сегодня я столкнулся с одной и той же проблемой и решил ее, не используя прокси create-react-app
сервер create-react-app
, но вместо этого создав прокси-сервер в моем приложении для create-react-app
.
В конце моего экспресс-приложения у меня есть
// all routes above
if (env.isDevelopment()) {
const proxy = require('express-http-proxy')
app.use('/*', proxy('http://localhost:3000'))
} else {
// probably serve up build version in production
}
Просто не забудьте выключить прокси-сервер в пакете json вашего клиента, иначе вы можете получить бесконечный прокси-цикл или что-то еще.
Ответ 3
EDIT: Мой предыдущий ответ не имел никакого отношения к проблеме и не решал ее. Все в моем случае было вызвано registerServiceWorker в CLI, сгенерированном index.js. Просто удалите его, и все работает так, как должно.
//Remove this lines from index.js
import registerServiceWorker from './registerServiceWorker'
registerServiceWorker();
Ответ 4
Вы можете добавить свой локальный сервер для создания реакции на веб-приложение api. Перейдя на console.developers.google.com и добавьте локальное приложение create-react-app в "Авторизованные исходники JavaScript" и "Авторизованные URI-адреса перенаправления".
Ответ 5
Я исправил эту проблему, используя поле "Valid UAuth redirect URIs" в настройках Facebook Developer для разделов продуктов Facebook Login, например http://your-domain.loc:5000/auth/facebook
.
И кнопка Facebook Auth должна быть:
<a href="#" onclick="location.href='http://your-domain.loc:5000/auth/facebook'; return false;">Login with Facebook</a>
Вы должны поместить туда свой URL-адрес перенаправления facebook. Еще одна вещь из моего примера: я использую 3000 портов для локального сервера узлов и 5000 для запроса API в своем приложении.
Я использую /etc/hosts
для использования моего домена, а не localhost
.
127.0.0.1 your-domain.loc
Работает для меня.
Кроме того, продолжается обсуждение ресурса GitHub с вопросом - https://github.com/facebook/create-react-app/issues/3502