How do I show the Google passport oAuth consent screen in the react frontend, not with express views template

Viewed 621

I am using express on the backend and React on the frontend. I want to show a screen like this:

enter image description here

In express, I have this setup:


config/passport-setup.js

const passport = require("passport")
const GoogleStrategy = require("passport-google-oauth20").Strategy
const User = require("../models/User")

passport.use(
  new GoogleStrategy(
    {
      clientID: process.env.clientID,
      clientSecret: process.env.clientSecret,
      callbackURL: "/auth/google/redirect",
    },
    (accessToken, refreshToken, profile, done) => {
      // passport callback function
      // console.log("passport callback function fired")


      // check if the user exists
      User.findOne({ googleID: profile.id }).then((currentUser) => {
        if (!currentUser) {
          // if the user doesn't exist, create a new user
          new User({
            username: profile.displayName,
            googleID: profile.id,
          })
            .save()
            .then((newUser) => {
              console.log(`New user created- ${newUser}`)
            })
        }

        if (currentUser) {
          console.log(`The current user is- ${currentUser}`)
        }
      })
    }
  )
)


app.js(handling backend router)

const authRouter = require("./routes/auth")
const passportSetup = require("./config/passport-setup")

routes/auth.js

const express = require("express")
const passport = require("passport")
const router = express.Router()


// auth with google
router.get("/google", passport.authenticate("google", {
    scope: ["profile"]
}))

// callback route for google to redirect to
router.get("/google/redirect", passport.authenticate("google"), (req, res) => {
    res.json({ message: "redirected "})
})

module.exports = router

I am following NetNija's tutorial on YouTube and he's using ejs template. But I'm using react. I have a NavBar component that has a Link, and in App.js I have the routes.


NavBar.js

 <Link to="/auth/google">
   <Button>Login with Google</Button>
 </Link>

App.js

import React, { Component } from "react"
import { BrowserRouter as Router, Route, Switch } from "react-router-dom"
import HomePage from "../components/HomePage"
import oAuthPage from "../containers/oAuthPage"

class App extends Component {
  render() {
    return (
      <div>
        <Router>
          <Switch>
            <Route exact path="/" component={HomePage} />
            <Route path="/auth/google" component={oAuthPage} />
          </Switch>
        </Router>
      </div>
    )
  }
}

export default App

Right now, oAuthPage is just displaying an h1 tag(I was testing if it's working or not), but I want to show that view from passport.


In summary, I want that:

  • User clicks on Login with Google button, gets redirected to the consent screen(the image that I have linked). The route is /auth/google.

  • In the consent screen, when the user chooses the account, it gets redirected to the route /auth/google/redirect from where it then fires off a callback function which then retrieves user profile from google.

  • With the info coming from google, I can create the user in the database with the displayName and googleID, and store the user in the db.

From my understanding, when i click on the button, a request is sent to the /auth/google api which sends a response to the frontend. And that response includes that consent screen?? I'm not able to figure it out. Need some help here.

1 Answers

Initially I was facing the same issue, but I found a workaround. Since google has it's own consent screen, which will be opened when you call the url /auth/google, you can't make a fetch request for this URL. So what can be done is using an anchor tag to make the redirection like this. (In Navbar.js make this change. Instead of using Link, use anchor tag)

<a class="google-link" href="http://localhost:5000/auth/google">
      <Button> Continue with Google </Button> 
</a>

And in backend, on the call back route use res.redirect('youre_url') to redirect back to UI, like this.

router.get('/google/redirect', passport.authenticate('google'), (req,res) => {
    if(req.user) {
        res.redirect(`http://localhost:3000/`);
    }
    else {
        res.redirect(`http://localhost:3000/login`);
    }
})

Also note that, you can't use res.json() since the google callback has a different origin.

Related