Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can anyone share an example of next js with passport google oauth2 integration?

If you have an example of code from any of your projects for nextjs using passport google oauth2, please share. There are some examples online for this using just nodejs but the mechanism of routes, middleware and callback is different with nextjs and I have not found a working example.

I have the following code but get a CORS error. I have seen youtube videos with google auth demos on localhost. The credentials I created also use localhost.

\lib\Passport.js

import passport from 'passport';

import { Strategy as GoogleStrategy } from 'passport-google-oauth20';

passport.serializeUser((user, done) => {
  done(null, user._id);
});

passport.deserializeUser((req, id, done) => {
  req.db
    .collection('users')
    .findOne({ _id: id })
    .then((user) => done(null, user));
});

passport.use(new GoogleStrategy({
  clientID: process.env.GOOGLE_CLIENT,
  clientSecret: process.env.GOOGLE_SECRET,
  callbackURL: process.env.WEB_URI+"/users/callback/google",
  passReqToCallback: true,
},
function(accessToken, refreshToken, profile, cb) {
  // User.findOrCreate({ googleId: profile.id }, function (err, user) {
  //   return cb(err, user);
  // });
  console.log("profile below")
  console.log(profile)
}
));

export default passport;

\pages\login.js with button - "Login using Google"

  <Button
  variant="outlined"
  color="secondary"
  startIcon={">"}
  onClick={(event) => {
    googleLogin(event) }}
  >
    Login using Google
  </Button>

and the function in \pages\login.js

  async function googleLogin(e) {
    const res = await fetch('/api/authGoogle', {
      method: 'GET',
      headers: { 'Content-Type': 'application/json' },
    })
    console.log(res);
    return;
  }

And the \pages\api\authGoogle.js

import nextConnect from 'next-connect';
import middleware from '../../middlewares/middleware';
import passport from '../../lib/passport';

const handler = nextConnect();

handler.use(middleware);

handler.get(passport.authenticate("google", {
  scope: ['profile', 'email', 'openid'], 
}))

handler.delete((req, res) => {
  req.logOut();
  res.status(204).end();
});

export default handler;

What I do not have is code for users/callback/google and I am not sure what to write in it. The official passportjs example used just nodejs and hard to follow so any sample using next js will help me and others in future.

like image 611
Kal Avatar asked Sep 12 '20 15:09

Kal


People also ask

Does passport js use OAuth?

Thankfully, Passport shields an application from the complexities of dealing with OAuth variants. In many cases, a provider-specific strategy can be used instead of the generic OAuth strategies described below. This cuts down on the necessary configuration, and accommodates any provider-specific quirks.


1 Answers

After a lot of time struggling, I figured bits and pieces myself.

Step 1 For Oauth, we have to link to the provider using a button/link directly. WE cannot use a fetch api call that goes to api first.

Will not work await fetch('/api/authGoogle

Will work href="/api/authGoogle

Step 2

In api/authGoogle the passport.authenticate needs to be called. handler.get(passport.authenticate("google", {scope: ['profile', 'email']}));

Step 3

In passport.js or wherever you have all the strategies

passport.use(new GoogleStrategy({
  clientID: process.env.GOOGLE_CLIENT,
  clientSecret: process.env.GOOGLE_SECRET,
  callbackURL: process.env.WEB_URI+"/api/auth/callback/google",
  passReqToCallback: true,
},   
async (req, accessToken, refreshToken, profile, done) => {
  console.log(profile)
  // add code here to check if user exists in database or create a new one

The way it works is /api/auth/callback/google gets passed a code (code=...) that you see in the browser url. The details are then passed from callback and available for console.log(profile) above.

Step 4

Callback file /api/auth/callback/google should look like this. I am just redirecting to home but you can set a browser cookie in this file. Install 'cookies' which is a very popular library if you want to do that.

handler.get(passport.authenticate("google"), (req, res) => {
  res.writeHead(302, {
    'Location': '/'
  });
  res.end();
})

Here passport.authenticate is repeated again but it was in step 2. Thats because the code needs to be used to get the profile information using the above line.

like image 186
Kal Avatar answered Sep 24 '22 04:09

Kal