Drop-in Google OAuth for Express and Next.js. No Passport.js needed.
npm install zoogleimport express from 'express'; import googleAuth from 'zoogle'; const app = express(); googleAuth.configure({ google: { clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, callbackURL: 'http://localhost:3000/auth/google/callback', }, jwt: { secret: process.env.JWT_SECRET, }, async findOrCreateUser(profile) { // Your database logic return await User.findOrCreate({ googleId: profile.id }); }, }); // Mount routes app.use('/auth/google', googleAuth.routes); // Protect routes app.get('/profile', googleAuth.middleware, (req, res) => { res.json({ user: req.user }); });// lib/zoogle.ts import googleAuth from 'zoogle'; googleAuth.configure({ google: { clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, callbackURL: 'http://localhost:3000/auth/google/callback', }, jwt: { secret: process.env.JWT_SECRET!, }, async findOrCreateUser(profile) { // Your database logic return await User.findOrCreate({ googleId: profile.id }); }, onSuccess: (user, token, req, res) => { (res as any).redirect(`/?token=${token}`); }, }); export default googleAuth;// pages/auth/google/login.ts import googleAuth from '../../lib/zoogle'; export default googleAuth.nextjs.loginHandler;// pages/auth/google/callback.ts import googleAuth from '../../lib/zoogle'; export default googleAuth.nextjs.callbackHandler;// pages/api/profile.ts import { withAuth } from 'zoogle'; async function handler(req, res) { res.json({ user: req.user }); } export default withAuth(handler);// Login button <a href="/api/auth/google/login"> <button>Login with Google</button> </a>; // Make authenticated requests fetch('/api/profile', { headers: { Authorization: `Bearer ${token}`, }, });Done! π
- Go to Google Cloud Console
- Create project β Enable Google+ API β Create OAuth credentials
- Add redirect URL:
http://localhost:3000/auth/google/callback(Express) orhttp://localhost:3000/api/auth/google/callback(Next.js) - Copy your
CLIENT_IDandCLIENT_SECRET
| Option | Type | Required | Description |
|---|---|---|---|
google.clientId | string | Yes | From Google Console |
google.clientSecret | string | Yes | From Google Console |
google.callbackURL | string | Yes | Where Google redirects back |
jwt.secret | string | Yes | Secret for JWT signing |
jwt.expiresIn | string | No | Default: "7d" |
findOrCreateUser | function | Yes | Your DB logic |
onSuccess | function | No | Custom success handler |
onError | function | No | Custom error handler |
Express router with two routes:
GET /login- Redirects to GoogleGET /callback- Handles Google response
Protects routes. Checks for valid JWT in Authorization: Bearer <token> header.
Object containing Next.js-specific handlers:
loginHandler- API route handler for logincallbackHandler- API route handler for callbackwithAuth- Higher-order function to protect API routes
Protects Next.js API routes. Wrap your handler with this function:
import { withAuth } from 'zoogle'; export default withAuth(async (req, res) => { // req.user is available here res.json({ user: req.user }); });Zoogle works with any version of Express (4.x, 5.x) and Next.js (13.x+). It uses version-agnostic type definitions and dynamic module resolution to maintain compatibility across releases.
| Framework | Supported Versions | Status |
|---|---|---|
| Express | β₯4.0.0 | β |
| Next.js | β₯13.0.0 | β |
| Next.js (App Router) | β₯13.0.0 | β |
Zoogle uses:
- Version-agnostic type definitions - No direct imports from framework types
- Dynamic module resolution -
require()to load Express/Next modules at runtime - Generic request/response handling - Works with any compatible framework version
- Optional peer dependencies - You choose which versions to install
Zoogle provides comprehensive error handling with custom error classes and helpful error messages. See the detailed Error Handling Guide for:
- π Configuration Errors - Catch missing or invalid config at startup
- π Runtime Errors - Handle OAuth and database errors gracefully
- π Authentication Errors - Use error codes for reliable frontend handling
Quick example:
import googleAuth, { ZoogleConfigError } from 'zoogle'; try { googleAuth.configure({ // ... your config }); } catch (error) { if (error instanceof ZoogleConfigError) { console.error('Config field:', error.field); console.error('How to fix:', error.hint); } }Frontend token handling:
// Reliable error handling with error codes axios.interceptors.response.use( (response) => response, (error) => { const { error_code } = error.response?.data || {}; if (error_code === 'token_expired') { return refreshToken().then(retry); } if (error_code === 'token_invalid') { redirectToLogin(); } }, );π Read the full Error Handling Guide
See examples/ folder.
- Express Example - Basic Express setup
- Next.js Example - Complete Next.js app with frontend
π Zoogle Auth Template
Add Google Login to ANY Express project in literally 2 minutes! A beautiful, production-ready authentication template powered by Zoogle. Just copy, paste, and you're done! β¨
People learn from examples!
Create: examples/basic-express/
File structure:
examples/basic-express/ βββ package.json βββ .env.example βββ src/ β βββ app.ts βββ README.md