skip to Main Content

TLDR: How do I initiate the Facebook Auth process from a page in my React application?

I’ve found quite a few posts that touch on most, but not all, of the items I’ve listed in the title of this post. And I’m pretty close to getting this working, but there must be something I’m missing.

My app consists of a create-react-app front-end using react-router for routing. I have this running on port 51000 in my development environment. In package.json, I’m using “proxy” to redirect other routes to my express server, running on port 51001. This works in general for making requests within my React components that hit the server. For example:

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

When calling within my React component, this will successfully hit my Express server.

I want to ensure that my back-end routes are authenticated, and I’ve chosen to use Facebook auth via passport-facebook. I’ve set this up just like the many online tutorials I’ve seen. For example, I have a route on my express server named ‘/auth/facebook’. If I go to localhost:51001/auth/facebook, it redirects me to facebook to login, and then redirects me back to some the route I gave it. So that flow works as expected.

The specific problem I’m having is getting React to successfully initiate and complete the api call that triggers auth. I have tried two approach.

Approach 1: Calling the route via ajax

I called the following in my componentDidMount:

axios.get('/auth/facebook')

This successfully hits my express server, but then immediate generates the following error in the browser console:

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.

**Approach 2: Going to the route in the browser **

The other thing I’ve tried, which I’ve seen in all the tutorials, is to add a link to one of my pages that simply navigates to the authentication route. For example:

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

However, when I click this, I just end up at http://localhost:51000/auth/facebook, or just a blank page in my React app. The proxy I have doesn’t kick in, and I don’t see any activity on my Express server when I go to this route in the browser, even though it’s not a Route I’ve defined in react-router.

So I’m a bit stuck here. Should clicking that tag have triggered that route to be fired against my Express server? Is there a way to tell react-router to ignore certain routes so that they’re redirected to my express server? This seems to work fine when making AJAX calls, but if I go to localhost:51000/not/a/route, this doesn’t cause the request to be redirected to Express. It just loads a react page with no content.

Any help is appreciated.

Thanks,

-Dan

EDIT

So I kind of have this working now, though I’m not at all confident it’ the “right” way to do things.

In my react app (which recall is running on port 51000), I have the following link:

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

Note that this is pointing directly at my API server, not at a react route. Navigating to this link hits the express server, and immediately redirects to Facebook. Logging in redirects back to my Express facebook callback, which itself redirects to http://localhost:51000/somePage, which is now back to my react app.

Ideally that tag would be going to a /api/auth/facebook, instead of hard-coded to go to a different URL/port. I’ll update this issue if/when I figure out how to get react-router to pass that through instead of treating it like a page it needs to load.

EDIT 2

I’m open to someone telling me otherwise, but I think my current approach is actually pretty much fine. I considered how things will behave in production. I will have my react site at www.example.com, with my express server accessible via api.example.com. My link to the Facebook login will be to “api.example.com/auth/facebook”. The callback, assuming successful auth, will redirect to “www.example.com/some/route”. I think it’s reasonable to bounce over to the “api” URL to perform the login. Ultimately there’s no point in trying to get react-router to ignore certain routes, since all of my api calls will be to an explicit route.

I realize I’m not providing a complete helpful solution to others. Once I have it all put together, I’ll include a link to my repo that contains this login flow, in case anyone else finds it helpful.

** EDIT 3 **

Here are links to my project. It won’t be trivial to get the whole project running, but there are only a handful of files associated with the auth flow.

You can view the repo here: https://github.com/dan-goyette/Portfolio

The Express server router for this is here:

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

In the UI, I’m triggering calls to the express server using this component:

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

You can see it working at https://www.dan-goyette.com/home, the button at the top right.

6

Answers


  1. I ran into the same problem today and solved it by not using create-react-app‘s proxy, but instead setting up a proxy in my backend to the create-react-app.

    At the end of my express app, I have

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

    Just remember to turn off the proxy in the package json of your client, or else you could end up with an infinite proxy loop or something.

    Login or Signup to reply.
  2. I was also running into this issue – changing the CRA proxy config seemed to do the trick:

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

    Where the OAuth link is located at /api/auth/foo, CRA app is at localhost:3000, and the express app is at localhost:3001

    Login or Signup to reply.
  3. EDIT: My previous answer had nothing to do with the issue and did not solve it. The whole thing in my case was caused by the registerServiceWorker in CLI generated index.js. Just remove it and everything works like it should.

    //Remove this lines from index.js
    import registerServiceWorker from './registerServiceWorker'
    
    registerServiceWorker();
    
    Login or Signup to reply.
  4. You can add your create react app localhost server to the web api By going to the console.developers.google.com and add the create-react-app localhost to the “Authorised JavaScript origins” and “Authorised redirect URIs”.

    Login or Signup to reply.
  5. I fixed this issue by using “Valid OAuth redirect URIs” field in Facebook Developer settings for Facebook Login product sections, for example, http://your-domain.loc:5000/auth/facebook.

    And the Facebook Auth button should be:

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

    You should put there your facebook redirect URL. One more thing from my example: I use 3000 port for local node server and 5000 for API request on my App.

    I use /etc/hosts for using my domain, not localhost.

    127.0.0.1   your-domain.loc
    

    Works for me.

    Also, additional discussion is going on the GitHub resource with issue – https://github.com/facebook/create-react-app/issues/3502

    Login or Signup to reply.
    • Add localhost in the Facebook developer setting (Facebook login)

    • Facebook login is working only with https, you should setup
      your localhost to work with https

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search