Back to List

Google Login Implementation β€” Passport + OAuth

Implement social login using Passport.js's Google Strategy. Covers the entire flow, from console setup to callback processing.

Intermediate
|
15min
|
Verified (2026-07)
Google LoginPassportOAuth Implementationpassport-google-oauth20Social Authentication
Progress0/55 (0%)

Implementing Google Login β€” Passport + OAuth

After completing this topic

You will be able to configure an OAuth client in the Google Cloud Console and implement social login using Passport.js's Google Strategy.


Prerequisites

You need to understand the following concepts from previous topics:

  • OAuth 2.0 Flow β€” The four players in the Authorization Code Flow
  • Passport.js β€” The Strategy pattern and serializeUser/deserializeUser
  • Express Session β€” Session-based authentication

These three concepts work together to enable Google login.


Step 1 β€” Google Cloud Console Setup

You need to register our app with Google. This process involves web console tasks rather than code.

  1. Google Cloud Console β†’ Create a new project
  2. "OAuth consent screen" β†’ Enter app name and email
  3. "Credentials" β†’ Create OAuth 2.0 client ID
  4. Add http://localhost:3000/auth/google/callback to the authorized redirect URIs.

As a result, you will receive two values: Client ID and Client Secret. Store these values in your .env file.

text
GOOGLE_CLIENT_ID=abc123...
GOOGLE_CLIENT_SECRET=xyz789...

Step 2 β€” Package Installation

bash
npm install passport-google-oauth20

Assume that passport and express-session are already installed.


Step 3 β€” Register the Strategy

javascript
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;

passport.use(new GoogleStrategy({
    clientID: process.env.GOOGLE_CLIENT_ID,
    clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    callbackURL: '/auth/google/callback',
  },
  (accessToken, refreshToken, profile, done) => {
    // The Google user information is contained in profile.
    // Find or create the user in the database.
    const user = {
      googleId: profile.id,
      name: profile.displayName,
      email: profile.emails[0].value,
      photo: profile.photos[0].value,
    };

    // In reality, perform a database query/save operation.
    done(null, user);
  }
));

This callback function is called after Google completes the authorization code-to-token exchange. Passport handles all the complexities of the OAuth flow, and we just receive the user information.


Step 4 β€” Connect the Routes

javascript
// Start Google login
app.get('/auth/google',
  passport.authenticate('google', { scope: ['profile', 'email'] })
);

// Google sends the authorization code here
app.get('/auth/google/callback',
  passport.authenticate('google', { failureRedirect: '/login' }),
  (req, res) => {
    res.redirect('/');
  }
);

// Logout
app.get('/logout', (req, res) => {
  req.logout(() => {
    res.redirect('/');
  });
});

Let's follow the flow:

  1. The user accesses /auth/google β†’ Redirected to the Google login screen.
  2. The user logs in to Google and grants permissions β†’ Google redirects to /auth/google/callback?code=xxx.
  3. Passport exchanges the code for a token β†’ The Strategy callback is invoked β†’ The user is stored in the session.
  4. res.redirect('/') β†’ Redirected to the home page with the user logged in.

Step 5 β€” Serialize/Deserialize

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

passport.deserializeUser((googleId, done) => {
  // In reality, query the database for the user by googleId.
  done(null, { googleId, name: '...' });
});

serialize defines what to store in the session, and deserialize defines how to restore the user object from the value retrieved from the session.

Instead of storing the entire user object in the session, store only the ID. Reducing the size of the session data reduces the server load.


Overall Structure

text
User                Our Server           Google
  β”‚                    β”‚                   β”‚
  β”œβ”€ /auth/google ─────→│                   β”‚
  β”‚                    β”œβ”€ redirect ────────→│
  β”‚                    β”‚                   β”‚
  │←── Google login screen ──                   β”‚
  β”‚                    β”‚                   β”‚
  β”œβ”€ Login+Permission ───────→│                   β”‚
  β”‚                    │←── code ───────────
  β”‚                    β”œβ”€ code+secret ─────→│
  β”‚                    │←── access_token ───
  β”‚                    β”œβ”€ token ───────────→│
  β”‚                    │←── profile ────────
  │←── Session created, / ──────                   β”‚

Passport handles the middle five steps (receiving the code β†’ exchanging it for a token β†’ requesting the profile) in a single Strategy. All we have to do is register the Strategy and connect the routes.


Common Mistakes

  1. Redirect URI mismatch β€” The URI registered in the console must be exactly the same as the callbackURL in the code. An error can occur even if there is only one slash difference.
  2. Missing scope β€” If you don't include scope: ['profile', 'email'], profile.emails will be undefined.
  3. Client Secret exposure β€” Store it in .env and add .env to .gitignore. If the Secret is uploaded to GitHub, Google will automatically disable it.

Key Takeaway

Passport.js + Google Strategy wraps all the complexities of the OAuth 2.0 flow into a single Strategy. All we have to do is Console setup β†’ Strategy registration β†’ Connect 2 routes. Key flow: /auth/google β†’ Google login β†’ /auth/google/callback β†’ Session creation β†’ Redirect to home.

πŸ’¬ Questions & Comments

0 comments

You can post without signing in. Guest comments cannot be edited or deleted by their author.

0/2000

Loading...