Google Authentication in a MERN Stack Application with Passport.js
Integrating third-party authentication systems like Google can save time and effort and provide security for the process. This blog will walk you through the steps of implementing Google OAuth authentication in a MERN stack app (MongoDB, Express, React, Node.js) using Passport.js—a popular authentication middleware for Node.js.
what is OAuth ?
OAuth (Open Authorization) is an open standard for authorization. It allows third-party services (Google) to exchange user data without exposing login credentials (like passwords). Instead of sharing their username and password with yout app directly, OAuth uses tokens to authorize access to users ….
Passport js
Passport.js is a middleware library for Node.js that provides middlewares and functions to implement various OAuth authentication strategies like "Login with Google," "Login with Facebook" "Login with Twitter”
OAuth strategies for passport
passport-google-oauth20
(Google login)passport-facebook
(Facebook login)passport-twitter
(Twitter login)
When you implement Google authentication using Passport.js, the flow typically looks like this:
User clicks "Login with Google" button.
form GET request to
/api/auth/google
end point in your backend.Passport middleware will redirect to google login page where user select their account and grants permission
Google redirects the user to the callback route (
/api/auth/google/callback
) and send profile info , access tokenPassport.js middleware handles this callback and extracts the user information from Google.
JWT token is generated and sent to the frontend, logging the user in.
Now, let’s go deeper into each part of this process:
1. User clicks "Login with Google"
When the user clicks the "Login with Google" button on your frontend, it triggers a request to your backend. You likely have a route that will be something like:
// Frontend button click that makes a GET request to /api/auth/google
const handleGoogleLogin(){
// make GET request to /api/auth/google
}
<button onClick={handleGoogleLogin} >
Login with Google
</button>
2. Redirect to /api/auth/google
route
The user is redirected to the backend route /api/auth/google
. This is where Passport.js, specifically the Google strategy (using passport-google-oauth2
or passport-google-oauth20
), comes into play. Let’s look at this part of the backend:
// In your Express app
app.get('/api/auth/google', passport.authenticate('google', {
scope: ['profile', 'email'] // The data you want from Google
}));
What happens here:
The
passport.authenticate('google')
middleware will initiate the OAuth 2.0 flow.It will redirect the user to Google’s login page, where they can select their Google account and approve the permissions requested by your app.
Important: Passport.js doesn't directly call the Google login page; it simply redirects the user to Google by forming the appropriate OAuth URL. The actual interaction with Google's login page is handled by the OAuth 2.0 protocol under the hood.
3. User selects profile and grants permission
On Google’s page, the user will see a prompt asking them to allow access to their account.
After the user selects their profile , google with verify it internally if success
Google will issue an authorization code and redirect to callback URL in your backend.
Google redirects to /api/auth/google/callback
with Authorization code
Once google authenticates and grants permission, it will be redirecte to the callback route you have defined. and pass the Authorization code
what is authorisation code? after granting permission google will not straight away pass the users info because of security reasons.. it will redirect to callback url and pass this authorization code.
authorization code is its a temporary code that represents the fact that the user has granted permission for your app to access their data.
and this authorization code by itself is not useful for accessing the user's profile data. You need to exchange it for an access token.
using access token … u can get users data
passport.use(new GoogleStrategy({...}))
middleware interupts here to exchange authorization code for acess token and get users data
What happens behind the scenes (Exchange Process):
Your server through Passport.js sends the authorization code to Google’s OAuth2 token endpoint (
https://oauth2.googleapis.com/token
), along with:The authorization code (that Google sent you).
The client ID and client secret (credentials of your app registered with Google).
The redirect URI (must match the one used earlier in the
passport.authenticate
call).
Passport will receive a set of parameters from Google:
accessToken
: This is the token you need to authenticate API requests to Google. It allows you to access Google data (like the user's profile).refreshToken
(optional): If you request offline access, this token allows you to refresh theaccessToken
when it expires without needing the user to log in again.profile
: This contains the user's profile data (like name, email, etc.) that Google sends after successful authentication.
You don’t need to manually exchange the authorization code for an access token in this case because Passport does that for you automatically behind the scenes as part of the OAuth flow.
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: '/auth/google/callback',
}, async (accessToken, refreshToken, profile, done) => {
try {
// write code to get user details from profile and save it in DB
// generte jwtToken
return done(null, jwtToken); // Pass the token to the done callback
} catch (error) {
return done(error, false); // If there's an error, pass it to the done callback
}
}));
now after this middle the actual function in /api/auth/google/callback
route is executed where i simply send the jwt token that i receive from the above middleware
app.get('/api/auth/google/callback',
passport.authenticate("google", (err, jwtToken) => {
if (err) {
return res.status(401).json({ message: "Authentication failed" });
}
res.cookie('token', jwtToken, { httpOnly: true });
return res.redirect('frontendpage');
})(req, res);
});
Summarizing
Where does Passport Middleware Come Into Play?
The first middleware (
passport.authenticate('google')
) triggers the redirection to Google and handles the OAuth flow.The second middleware (
passport.authenticate('google')
) is executed when Google redirects back to the callback route. It validates the user's authorization code, exchanges it for the access token, and stores the user's profile inreq.user
.
Summary of Important Functions:
passport.authenticate('google')
– Redirects the user to Google’s login page.Callback route (
/api/auth/google/callback
) – Handles the response from Google and processes the access token and user info.req.user
– Contains the authenticated user's information (e.g., email, name).JWT generation – Once the user is authenticated, generate a JWT token and send it to the frontend.
Subscribe to my newsletter
Read articles from Pavan Kumar K directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by