Introduction
Recently I decided to use NextJS on a project and after so many iterations, I decided to use google authentication with passport. In this article, I would be giving a step by step guide on how to set up authentication in your NextJS application with passport google strategy.
Essentials
Before we get started on the main course, here are a few things you need to know and have set up.
- You need to have basic knowledge of Javascript or Typescript as well as React (NextJS).
- You need to understand the concept of http requests and responses.
- You should have Node set up on your computer.
- You must have set up your application on Google developers console... you can check 'Register Application' section here on how to go about it.
In this article, I would be using yarn
as my package manager, you could go ahead to use npm
if you prefer.
First you would need to set up a NextJS project on your computer, so you go to your terminal to run the following command
yarn create next-app --typescript
You would be prompted to enter a name for the project, do so and press enter to proceed.
Once the set up is complete, you need to change directory to the newly setup project by running the next command
cd <your-project-name>
Next up, you install all the dependencies you need to successfully complete your authentication implementation which include:
To install, run the following command in your terminal
yarn add next-connect passport passport-google-oauth20 @types/passport @types/passport-google-oauth20
Next up, You need to add some credentials to your env file. Create a new file named .env
and add the following values
GOOGLE_CLIENT_ID: <your app client id>
GOOGLE_CLIENT_SECRET: <your app client secret>
After this, you can now go into writing the main code.
Now, we start coding!
In your root directory, create a new folder called lib
. Inside the lib
folder, create a new file named passport-google-auth.ts
In the passport-google-auth.ts
file, you configure google strategy using passport using the following code.
// /lib/passport-google-auth.ts
import { Profile, Strategy as GoogleStrategy } from "passport-google-oauth20";
import passport from "passport";
// logic to save your user or check if user exists in your record to proceed.
const saveUser = (user: Profile) => {
return new Promise((resolve, reject) => {
resolve("Successful");
});
};
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
callbackURL: "/api/oauth2/redirect/google", // this is the endpoint you registered on google while creating your app. This endpoint would exist on your application for verifying the authentication
},
async (_accessToken, _refreshToken, profile, cb: any) => {
try {
await saveUser(profile);
return cb(null, profile);
} catch (e: any) {
throw new Error(e);
}
}
)
);
// passport.serializeUser stores user object passed in the cb method above in req.session.passport
passport.serializeUser((user, cb) => {
process.nextTick(function () {
return cb(null, user);
});
});
// passport.deserializeUser stores the user object in req.user
passport.deserializeUser(function (
user: any,
cb: (arg0: null, arg1: any) => any
) {
process.nextTick(function () {
return cb(null, user);
});
});
// for broader explanation of serializeUser and deserializeUser visit https://stackoverflow.com/questions/27637609/understanding-passport-serialize-deserialize
// An article that explains the concept of process.nextTick https://nodejs.dev/learn/understanding-process-nexttick
export default passport;
Next up, you create a new file in /pages/api
folder named login.ts
.
Inside the login.ts
file, you create a get request that uses the google strategy method you configured with passport in the last step by adding the following code:
// /pages/api/login.ts
import passport from "../../lib/passport-google-auth";
import nextConnect from "next-connect";
export default nextConnect()
.use(passport.initialize())
.get(
passport.authenticate("google", {
scope: ["profile", "email"],
})
);
You will now create the callback url for verifying the authentication.
Go to api
folder in pages
, create a folder named oauth2
. Inside the oauth2
folder, create a folder named redirect
. Inside the redirect
folder, create a new file named google.ts
.
// /pages/api/oauth2/redirect/google.ts
import { NextApiRequest, NextApiResponse } from "next";
import nextConnect from "next-connect";
import passport from "../../../../lib/passport-google-auth";
export default nextConnect().get(
passport.authenticate("google"),
(req: NextApiRequest & { user: any }, res: NextApiResponse) => {
// you can save the user session here. to get access to authenticated user through req.user
res.redirect("/");
}
);
Now that you are done implementing the backend, you can now use the endpoints on the frontend.
Create a file named login in the pages folder and paste the following code for your login page.
// /pages/login.tsx
import Link from "next/link";
const LoginPage = () => {
return (
<div
style={{
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
height: "100%",
width: "100%",
textAlign: "center",
}}
>
<h1 style={{ fontSize: "2.5rem" }}>Login with Google</h1>
<Link href="/api/login" passHref>
<button
style={{
border: "1px solid black",
backgroundColor: "white",
borderRadius: "10px",
height: "50px",
width: "200px",
cursor: "pointer",
}}
>
Proceed
</button>
</Link>
</div>
);
};
export default LoginPage;
Voila, you can now authenticate your next app with google.
Conclusion
This article shows how you can leverage passport google strategy to authenticate your users in your next app.
You can access the code used in this tutorial here.
Disclaimer
This is my first technical article and I hope I did justice to the topic. Questions or feedback can be dropped in the comments. You can follow me on twitter and github
Top comments (6)
Small detail: Where does the
LoginPage
component go? It's not imported / used in any other component. Do you make a button first, and pop up the login? Do you need to know whether or not the person is logged in or not?Hi, I've updated the article to give a bit more direction on there the
LoginPage
goes.For more context, Next handles the routes in this scenario using the files in the
pages
folder nextjs.org/docs/routing/introductionOr If you want your login screen to be a pop up, then by all means, go for it.
If you check the
/lib/passport-google-auth.ts
file, thesaveUser
function is meant to help you store the user's authenticated state which you can use to handle authorisation in your app. I will write an article about Handling authentication in nextjs to show the way I go about it.Hey there, trying this and am getting
"Login sessions require session support. Did you forget to use
express-session
middleware?"on the redirect, did I miss a step? Thanks!
This article only highlights how you can authenticate a user using passports google library.
However you want to keep sessions of the user is up to you.
Thanks.
😍😍