Playbook

01. REST API Design Principles02. HTTP Methods and Status Co...03. Backend Fundamentals: 0104. Backend Fundamentals: 0205. GitHub OAuth in Node.js Ap...06. Google OAuth in Node.js Ap...07. MongoDB Aggregation08. Introduction to YAML09. Basics Concepts of Normali...10. Setting Up ESLint, Commit...11. Replication and Sharding12. Introduction to Redis13. Introduction to Kafka
Profile
Akkal DhamiFull Stack Developer

Building modern web experiences with a focus on performance, scalability, and clean architecture.

© 2026 | Akkal Dhami | All rights reserved

Built with
byAkkal Dhami

Navigation

  • Projects
  • Dev Setup
  • Playbook
  • Templates
  • Networking
  • SQL - MySQL
  • SQL Playground
  • DSA
AKKAL DHAMIAKKAL DHAMIAKKAL DHAMI

Google OAuth

What this covers

A practical Google OAuth flow using Passport, designed for stateless APIs.
This focuses on configuration, routing, and controller logic — not theory.

Stack

  • Node.js
  • Express
  • TypeScript
  • passport
  • passport-google2

Google OAuth Setup

  1. Go to your Google Settings
  2. Developer settings -> OAuth Apps -> New OAuth App
  3. Fill in the required information
  4. Set Homepage URL to http://localhost:9000 (or your production URL)
  5. Set Authorization callback URL to http://localhost:9000/api/auth/google/callback (or your production URL)
  6. Register application
  7. Generate a Client Secret
  8. Copy the Client ID and Client Secret

Implementation

Install packages

  • Dependencies
  • TypeScript types

Setup Environment variables

Add the following to your .env file:

.env
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"
GOOGLE_REDIRECT_URI="your-google-redirect-uri"

Setup Environment Configuration

src/configs/env.ts
import "dotenv/config";
 
interface Config {
  PORT: number;
  NODE_ENV: string;
  LOG_LEVEL: string;
 
  GOOGLE_CLIENT_ID: string;
  GOOGLE_CLIENT_SECRET: string;
  GOOGLE_REDIRECT_URI: string;
}
 
const env: Config = {
  PORT: Number(process.env.PORT) || 1111,
  NODE_ENV: process.env.NODE_ENV || "development",
  LOG_LEVEL: process.env.LOG_LEVEL || "info",
 
  GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID!,
  GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET!,
  GOOGLE_REDIRECT_URI: process.env.GOOGLE_REDIRECT_URI!
};
 
export default env;

Configure Passport with Google Strategy

src/configs/passport.ts
import passport from "passport";
import { Strategy as GoogleStrategy } from "passport-google-oauth20";
import env from "./env";
 
const clientID = env.GOOGLE_CLIENT_ID;
const clientSecret = env.GOOGLE_CLIENT_SECRET;
const callbackURL = env.GOOGLE_REDIRECT_URI;
 
passport.use(
  new GoogleStrategy(
    {
      clientID,
      clientSecret,
      callbackURL
    },
    function (accessToken, refreshToken, profile, cb) {
      return cb(null, profile);
    }
  )
);

Configure OAuth controller

src/controllers/oauth.controller.ts
import { NextFunction, Request, Response } from "express";
import { Profile } from "passport-google-oauth20";
 
import { ApiResponse } from "../utils/api-response";
import { AsyncHandler } from "../utils/async-handler";
import { ApiError } from "../utils/api-error";
 
//? login with google
export const googleOAuth = AsyncHandler(
  async (req: Request, res: Response, next: NextFunction) => {
    const data = req.user as Profile | undefined;
    const user = data?._json;
 
    if (!user || !data) {
      return next(ApiError.unauthorized("Authenticated failed!"));
    }
 
    const user = {
      provider: data?.provider,
      providerId: data.id,
      name: data.displayName,
      email: data?.emails && data?.emails[0]?.value,
      isEmailVerified: data?.emails && data?.emails[0]?.verified,
      avatar: data.profileUrl || (data.photos && data.photos[0].value)
    };
 
    //? save the data into your databases
 
    ApiResponse.ok(res, "Auth Successfull", {
      user
    });
  }
);

Configure OAuth routes

src/routes/oauth.routes.ts
import { Router } from "express";
import passport from "passport";
 
import { googleOAuth } from "../controllers/oauth.controller";
 
const router = Router();
 
router.get(
  "/google",
  passport.authenticate("google", {
    scope: ["email", "profile", "openid"],
    prompt: "consent"
  })
);
 
router.get(
  "/google/callback",
  passport.authenticate("google", {
    failureRedirect: "/login", //? redirect route if authenticated is failed
    session: false
  }),
  googleOAuth
);
 
export default router;

Mount routes

src/routes/index.ts
import { Router } from "express";
import OAuthRoutes from "./oauth.routes";
 
const router = Router();
 
router.use("/oauth", OAuthRoutes);
 
export default router;

Initialize passport

src/app.ts
import express, { Express, Request, Response } from "express";
 
import { notFoundHandler } from "./middlewares/not-found-handler";
import { errorHandler } from "./middlewares/error-handler";
 
import Routes from "./routes/index";
 
import "./configs/passport";
 
const app: Express = express();
 
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
 
// Routes
app.use("/api", Routes);
 
// Not found handler (should be after routes)
app.use(notFoundHandler);
 
// Global error handler (should be last)
app.use(errorHandler);
 
export default app;

Success Response

{
  "success": true,
  "message": "Auth Successfull",
  "statusCode": 200,
  "data": {
    "user": {
      "provider": "google",
      "providerId": "1163181840105620881",
      "name": "Akkal Dhami",
      "email": "dhamiakkal21@gmail.com",
      "isEmailVerified": true,
      "avatar": "https://lh3.googleusercontent.com/..."
    }
  }
}

CLI

05. GitHub OAuth in Node.js Applicatio...
07. MongoDB Aggregation