2017-06-29 103 views
14

TLDR: Jak zainicjować proces uwierzytelniania Facebooka ze strony w aplikacji React?Uwierzytelnianie za pomocą usługi Passport + Facebook + Express + create-response-app + React-Router + proxy

Znalazłem sporo postów, które dotykają większości, ale nie wszystkich, przedmiotów wymienionych w tytule tego wpisu. I jestem całkiem blisko tego działania, ale musi być coś, czego mi brakuje.

Moja aplikacja składa się z interfejsu front-end do tworzenia aplikacji z użyciem routera reagowania do routingu. Mam to działa na porcie 51000 w moim środowisku programistycznym. W package.json używam "proxy" do przekierowania innych tras do mojego serwera ekspresowego, działającego na porcie 51001. Generalnie działa to przy wysyłaniu żądań do moich komponentów React, które trafiają na serwer. Na przykład:

axios.get('/api/some-stuff') 

Podczas połączenia z moim komponentem React, zostanie on pomyślnie trafiony na moim serwerze Express.

Chcę się upewnić, że moje trasy z powrotem są uwierzytelnione, a ja wybrałem wykorzystanie uwierzytelnienia Facebook przez paszport-facebook. Ustawiłem to tak, jak wiele samouczków online, które widziałem. Na przykład mam trasę na moim ekspresowym serwerze o nazwie "/ auth/facebook". Jeśli przejdę do localhost: 51001/auth/facebook, przekieruje mnie to na facebooka, aby się zalogować, a następnie przekierowuje mnie z powrotem do trasy, którą dałem. Tak więc przepływ działa zgodnie z oczekiwaniami.

Specyficzny problem, który mam, polega na tym, że React pomyślnie inicjuje i wykonuje wywołanie api, które wyzwala auth. Próbowałem dwóch podejść.

Podejście 1: Wywołanie trasy za pośrednictwem ajax

Zadzwoniłem następujących w moim componentDidMount:

axios.get('/auth/facebook') 

ten skutecznie uderza moje wyraźne serwera, ale następnie natychmiastowe generuje następujący błąd w przeglądarce konsola:

XMLHttpRequest cannot load https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http% …2Flocalhost%3A51000%2Fauth%2Ffacebook%2Fcallback&client_id=XYZ. Redirect from ' https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http% …2Flocalhost%3A51000%2Fauth%2Ffacebook%2Fcallback&client_id=XYZ’ to ' 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' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin ' http://localhost:51000 ' is therefore not allowed access.

** Podejście 2: przejście do trasy w przeglądarce **

Inną rzeczą, którą wypróbowałem, co widziałem we wszystkich tutorialach, jest dodanie linku do jednej z moich stron, która po prostu przechodzi do trasy uwierzytelniania. Na przykład:

<a href="/auth/facebook">Login with Facebook</a> 

Jednak po kliknięciu tego, po prostu kończy się na http://localhost:51000/auth/facebook, lub po prostu pusta strona w moim React aplikacji. Proxy, którego mam, nie uruchamia się i nie widzę żadnej aktywności na moim Express serwerze, kiedy idę na tę trasę w przeglądarce, mimo że nie jest to Trasa, którą zdefiniowałem w routerze reagowania.

Więc trochę utknąłem tutaj. Czy kliknięcie tego tagu spowodowało uruchomienie tej trasy na moim serwerze Express? Czy istnieje sposób na poinformowanie routera reagowania, aby zignorował określone trasy, aby zostały przekierowane na mój serwer ekspresowy? Wydaje się to działać dobrze podczas wykonywania wywołań AJAX, ale jeśli przejdę do localhost: 51000/not/a/route, nie spowoduje to, że żądanie zostanie przekierowane do Express. Po prostu ładuje stronę reakcji bez zawartości.

Każda pomoc jest doceniana.

Dzięki,

-Dan

EDIT

Więc ja niby mam to działa teraz, choć nie jestem wcale przekonany, że to "prawo" sposób robić rzeczy .

W moim reagować aplikację (które przypominam jest uruchomiony na porcie 51000) Mam następujący link:

<a href="http://localhost:51001/auth/facebook">Facebook Login</a> 

pamiętać, że jest skierowana bezpośrednio w kierunku mojego serwera API, nie reagują na trasie. Nawigowanie do tego linku trafia na serwer ekspresowy i natychmiast przekierowuje na Facebooka. Zalogowanie przekierowań z powrotem do mojego Express facebook callback, który sam przekierowuje do http://localhost:51000/somePage, który jest teraz z powrotem do mojej aplikacji reagowania.

Idealnie by tag trafił do/api/auth/facebook, zamiast na sztywno zakodowany, aby przejść do innego URL/portu. Zaktualizuję ten problem, jeśli/kiedy wymyślę, jak uzyskać router reagowania, aby przekazał to zamiast traktować go jak stronę, którą musi załadować.

EDIT 2

Jestem otwarty do kogoś mówi mi inaczej, ale myślę, że moje obecne podejście jest faktycznie dość dużo w porządku. Zastanawiałem się, jak będą się zachowywać rzeczy w produkcji. Moja strona internetowa z reakcją będzie dostępna pod adresem www.example.com, a mój serwer ekspresowy będzie dostępny za pośrednictwem api.example.com. Mój link do loginu Facebooka to "api.example.com/auth/facebook". Połączenie zwrotne, pod warunkiem pomyślnego uwierzytelnienia, przekieruje do "www.example.com/some/route". Uważam, że rozsądnie jest przeskoczyć do adresu URL "api", aby wykonać logowanie. Ostatecznie nie ma sensu próbować zmusić routera reagującego do zignorowania pewnych tras, ponieważ wszystkie moje połączenia api będą do wyraźnej trasy.

Zdaję sobie sprawę, że nie dostarczam pełnego pomocnego rozwiązania innym osobom. Kiedy już wszystko razem wziąłem, dołączę link do mojego repozytu zawierającego ten proces logowania, na wypadek gdyby ktoś inny uznał to za pomocne.

** EDYTUJ 3 **

Oto linki do mojego projektu. Wykonanie całego projektu nie będzie trywialne, ale z przepływem uwierzytelniania wiąże się tylko garstka plików.

można zobaczyć tutaj: https://github.com/dan-goyette/Portfolio repo

Express Router serwer bo to jest tutaj:

https://github.com/dan-goyette/Portfolio/blob/master/portfolio-server/src/Routing/auth.js

W interfejsie mam wyzwalanie połączeń do serwera wyraźnej użyciu tego składnika :

https://github.com/dan-goyette/Portfolio/blob/75ca9326e6227d0601cdfa4c0cece672bd347302/portfolio-ui/src/Components/SocialMenuButton/SocialMenuButton.js

Widać to działa na https://www.dan-goyette.com/home, przycisk w prawym górnym rogu.

+0

Czy kiedykolwiek znaleźć rozwiązanie na to, że umożliwia przepływ Redux-thunk? Nie chciałbym, żeby ta część została wykonana z hrefem – KellysOnTop23

+1

Nie używam redux, więc nie jestem pewien, co jest wymagane, ale edytuję swój post, aby umieścić linki do mojego projektu, które pokazują moje rozwiązanie. – Dan

+0

Proszę! Redux nie zmienia naszego wspólnego problemu. Właśnie miałam zadowolić się twoim 'href' owiniętym ruchem przycisku. Czy przypadkiem znalazłeś sposób na wywołanie GET za pomocą aksios i nadal masz wywoływane wywołanie zwrotne? to byłaby najlepsza alternatywa dla mojego istniejącego kodu i zamierzonego użycia .... – KellysOnTop23

Odpowiedz

1

Wpadłem dziś na ten sam problem i rozwiązałem go, nie używając proxy create-react-app, ale zamiast tego ustawiłem proxy w moim zapleczu na create-react-app.

Pod koniec mojej wyraźnej aplikacji, mam

// 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 
} 

Wystarczy pamiętać, aby wyłączyć proxy w json opakowania klienta, albo może skończyć się z nieskończonej pętli proxy lub coś.

+0

Otrzymuję 'bundle.js: 1 Uncaught SyntaxError: nieoczekiwany token <' z tym podejściem. Aplikacja CRA działa poprawnie, gdy jest bezpośrednio dostępna. Oto mój kod węzła/ekspresowy: https://gist.github.com/bvodola/5640b237509dc061f754df2ad0812cee –

+0

brzmi to, jakby serwer służył do pliku index.html dla zasobu js, gdzie '<' jest początkiem '

+1

Witam, czy mogę wiedzieć, czy ta metoda działa również z danymi sesji?Posiadam ustawienia ekspresowego backendu z paszportem-facebookiem, uwierzytelnianie działa po stronie ekspresowej i mogę przekierować je z powrotem na moje trasy frontendowe. Czy istnieje sposób, że kiedy przekierowuję po auth, mogę zachować dane sesji (zalogowany użytkownik) i lub uzyskać logowany magazyn danych użytkownika w redux? Naprawdę utknąłem w tym! – LawrenceH

0

Byłem też działa w tej kwestii - zmiana konfiguracji serwerów proxy CRA wydawało się rade:

"proxy": { 
    "/api": { 
     "target": "http://localhost:3001/" 
    } 
} 

Gdzie link OAuth znajduje się /api/auth/foo CRA aplikacja jest na localhost:3000, a express aplikacja jest pod localhost:3001

+0

Próbowałem tej sztuczki dla podobnego problemu na 'paszporcie-twitterze' bezskutecznie. – wlh

0

EDYCJA: Moja poprzednia odpowiedź nie miała nic wspólnego z problemem i nie rozwiązała go. Cała sprawa w moim przypadku była spowodowana przez registerServiceWorker w CLI generowanym index.js. Po prostu go usuń i wszystko działa tak, jak powinno.

//Remove this lines from index.js 
import registerServiceWorker from './registerServiceWorker' 

registerServiceWorker(); 
+0

To nie rozwiązało problemu. – KellysOnTop23

+0

Nie wydaje się to być związane z przyczyną problemu. – wlh

0

można dodać create reagować aplikacji serwera localhost API internetowej przechodząc do console.developers.google.com i dodać tworzyć reagują aplikacji localhost do „upoważniony początków języka JavaScript” i „upoważniony przekierowania URI ".

0

Rozwiązałem ten problem, używając pola "Prawidłowe identyfikatory URI przekierowania OAuth" w ustawieniach dla programistów Facebooka dla sekcji z artykułami z logo Facebooka, na przykład http://your-domain.loc:5000/auth/facebook.

i przycisk Facebook Auth powinno być:

<a href="http://your-domain.loc:5000/auth/facebook">Login with Facebook</a> 

Należy umieścić tam swój facebook przekierowania. Jeszcze jedno z mojego przykładu: używam portu 3000 dla lokalnego serwera węzłów i 5000 dla żądania API w mojej aplikacji.

Używam /etc/hosts do korzystania z mojej domeny, a nie localhost.

127.0.0.1 your-domain.loc 

Działa u mnie.

Również dodatkowe dyskusja się dzieje zasobu GitHub z emisji - https://github.com/facebook/create-react-app/issues/3502