Skip to content

zaghamabbas786/multi-oauth

Repository files navigation

πŸ” Easy OAuth - The Simplest Multi-Provider OAuth Library for Node.js

npm version License: MIT TypeScript

Easy OAuth is the most developer-friendly OAuth authentication library for Node.js applications. Implement Google, Facebook, GitHub, Twitter, LinkedIn, Apple, and Microsoft login in just 3 lines of code!

Perfect for any Node.js backend framework - Express, Fastify, Koa, Hono, Next.js API Routes, and more.

✨ Why Easy OAuth?

  • πŸš€ Super Simple API - Just 2 methods: auth.url() and auth.callback()
  • 🎯 7 Providers Built-in - Google, Facebook, GitHub, Twitter, LinkedIn, Apple, Microsoft
  • πŸ’ͺ TypeScript Native - Full type safety with exported types
  • πŸ”„ Normalized Response - Consistent user object across all providers
  • πŸ“¦ Zero Dependencies - Lightweight and fast
  • 🎨 Framework Agnostic - Works with Express, Fastify, Koa, Hono, Next.js API, and any Node.js framework
  • πŸ›‘οΈ Production Ready - Battle-tested OAuth implementations

πŸ“¦ Installation

npm install multi-oauth
yarn add multi-oauth
pnpm add multi-oauth

πŸš€ Quick Start

TypeScript Example

import auth from 'multi-oauth';
import express from 'express';

const app = express();

// Step 1: Configure providers
auth.configure({
  providers: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!
    },
    github: {
      clientId: process.env.GITHUB_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!
    }
  },
  redirectUri: 'http://localhost:3000/callback'
});

// Step 2: Redirect to OAuth provider
app.get('/login/:provider', (req, res) => {
  const authUrl = auth.url(req.params.provider);
  res.redirect(authUrl);
});

// Step 3: Handle callback
app.get('/callback/:provider', async (req, res) => {
  try {
    const user = await auth.callback(req.params.provider, req);
    res.json(user);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

app.listen(3000, () => console.log('Server running on port 3000'));

JavaScript (CommonJS) Example

const auth = require('multi-oauth').default;
const express = require('express');

const app = express();

// Configure providers
auth.configure({
  providers: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET
    },
    facebook: {
      clientId: process.env.FACEBOOK_CLIENT_ID,
      clientSecret: process.env.FACEBOOK_CLIENT_SECRET
    }
  },
  redirectUri: 'http://localhost:3000/callback'
});

// Login route
app.get('/login/:provider', (req, res) => {
  res.redirect(auth.url(req.params.provider));
});

// Callback route
app.get('/callback/:provider', async (req, res) => {
  try {
    const user = await auth.callback(req.params.provider, req);
    res.json(user);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

app.listen(3000);

🎯 Supported Providers

Provider Status Scopes
Google βœ… Ready openid, profile, email
Facebook βœ… Ready email, public_profile
GitHub βœ… Ready user:email
Twitter βœ… Ready tweet.read, users.read
LinkedIn βœ… Ready openid, profile, email
Apple βœ… Ready name, email
Microsoft βœ… Ready openid, profile, email, User.Read

πŸ“– API Reference

auth.configure(config: OAuthConfig)

Configure the OAuth manager with your provider credentials.

auth.configure({
  providers: {
    google: {
      clientId: 'YOUR_CLIENT_ID',
      clientSecret: 'YOUR_CLIENT_SECRET',
      scope: ['openid', 'profile', 'email'] // Optional: custom scopes
    }
  },
  redirectUri: 'http://localhost:3000/callback'
});

auth.url(providerName: string, state?: string): string

Generate the OAuth authorization URL for a provider.

const authUrl = auth.url('google');
const authUrlWithState = auth.url('google', 'custom-state-value');

auth.callback(providerName: string, req: OAuthRequest): Promise<OAuthUser>

Handle the OAuth callback and get the user profile.

const user = await auth.callback('google', req);

Returns a normalized user object:

{
  id: string;           // Unique user ID from provider
  name: string;         // User's display name
  email?: string;       // User's email (if available)
  avatar?: string;      // Profile picture URL (if available)
  provider: string;     // Provider name (e.g., 'google')
  raw: any;            // Original response from provider
}

πŸ”§ Provider Configuration Guide

Google OAuth

  1. Go to Google Cloud Console
  2. Create a new project or select existing one
  3. Enable Google+ API
  4. Create OAuth 2.0 credentials
  5. Add authorized redirect URI: http://localhost:3000/callback/google
google: {
  clientId: 'xxx.apps.googleusercontent.com',
  clientSecret: 'GOCSPX-xxx',
  scope: ['openid', 'profile', 'email'] // Optional
}

Facebook OAuth

  1. Go to Facebook Developers
  2. Create a new app
  3. Add Facebook Login product
  4. Get App ID and App Secret
  5. Add redirect URI in settings
facebook: {
  clientId: 'YOUR_APP_ID',
  clientSecret: 'YOUR_APP_SECRET',
  scope: ['email', 'public_profile'] // Optional
}

GitHub OAuth

  1. Go to GitHub Settings β†’ Developer settings β†’ OAuth Apps
  2. Create a new OAuth App
  3. Get Client ID and Client Secret
  4. Set callback URL: http://localhost:3000/callback/github
github: {
  clientId: 'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET',
  scope: ['user:email'] // Optional
}

Twitter OAuth

  1. Go to Twitter Developer Portal
  2. Create a new app
  3. Enable OAuth 2.0
  4. Get Client ID and Client Secret
  5. Add callback URL
twitter: {
  clientId: 'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET',
  scope: ['tweet.read', 'users.read'] // Optional
}

LinkedIn OAuth

  1. Go to LinkedIn Developers
  2. Create a new app
  3. Get Client ID and Client Secret
  4. Add redirect URL
linkedin: {
  clientId: 'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET',
  scope: ['openid', 'profile', 'email'] // Optional
}

Apple Sign In

  1. Go to Apple Developer
  2. Create a Services ID
  3. Configure Sign in with Apple
  4. Get Service ID and Key
apple: {
  clientId: 'YOUR_SERVICE_ID',
  clientSecret: 'YOUR_PRIVATE_KEY',
  scope: ['name', 'email'] // Optional
}

Microsoft OAuth

  1. Go to Azure Portal
  2. Register a new application
  3. Get Application (client) ID
  4. Create a client secret
  5. Add redirect URI
microsoft: {
  clientId: 'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET',
  scope: ['openid', 'profile', 'email', 'User.Read'] // Optional
}

🌟 Framework Examples

Express.js

import auth from 'multi-oauth';
import express from 'express';

const app = express();

auth.configure({
  providers: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!
    }
  },
  redirectUri: 'http://localhost:3000/callback'
});

app.get('/login/:provider', (req, res) => {
  res.redirect(auth.url(req.params.provider));
});

app.get('/callback/:provider', async (req, res) => {
  try {
    const user = await auth.callback(req.params.provider, req);
    
    // Store user in session
    req.session.user = user;
    
    res.redirect('/dashboard');
  } catch (error) {
    res.redirect('/login?error=' + error.message);
  }
});

app.listen(3000);

Fastify

import auth from 'multi-oauth';
import fastify from 'fastify';

const app = fastify();

auth.configure({
  providers: {
    github: {
      clientId: process.env.GITHUB_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!
    }
  },
  redirectUri: 'http://localhost:3000/callback'
});

app.get('/login/:provider', async (request, reply) => {
  const { provider } = request.params;
  const authUrl = auth.url(provider);
  reply.redirect(authUrl);
});

app.get('/callback/:provider', async (request, reply) => {
  const { provider } = request.params;
  const user = await auth.callback(provider, request);
  reply.send(user);
});

Koa

import auth from 'multi-oauth';
import Koa from 'koa';
import Router from 'koa-router';

const app = new Koa();
const router = new Router();

auth.configure({
  providers: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!
    }
  },
  redirectUri: 'http://localhost:3000/callback'
});

router.get('/login/:provider', (ctx) => {
  ctx.redirect(auth.url(ctx.params.provider));
});

router.get('/callback/:provider', async (ctx) => {
  const user = await auth.callback(ctx.params.provider, ctx.request);
  ctx.body = user;
});

app.use(router.routes());

Next.js API Routes

// pages/api/login/[provider].ts
import auth from 'multi-oauth';
import type { NextApiRequest, NextApiResponse } from 'next';

auth.configure({
  providers: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!
    }
  },
  redirectUri: 'http://localhost:3000/api/callback'
});

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  const { provider } = req.query;
  res.redirect(auth.url(provider as string));
}

// pages/api/callback/[provider].ts
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { provider } = req.query;
  const user = await auth.callback(provider as string, req);
  // Handle user (set session, JWT, etc.)
  res.json(user);
}

Hono (Edge Runtime)

import auth from 'multi-oauth';
import { Hono } from 'hono';

const app = new Hono();

auth.configure({
  providers: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!
    }
  },
  redirectUri: 'http://localhost:3000/callback'
});

app.get('/login/:provider', (c) => {
  return c.redirect(auth.url(c.req.param('provider')));
});

app.get('/callback/:provider', async (c) => {
  const user = await auth.callback(c.req.param('provider'), c.req);
  return c.json(user);
});

πŸ›‘οΈ Error Handling

app.get('/callback/:provider', async (req, res) => {
  try {
    const user = await auth.callback(req.params.provider, req);
    res.json(user);
  } catch (error) {
    if (error.message.includes('not configured')) {
      res.status(500).json({ error: 'Provider not configured' });
    } else if (error.message.includes('code not found')) {
      res.status(400).json({ error: 'Authorization failed' });
    } else if (error.message.includes('Token exchange failed')) {
      res.status(401).json({ error: 'Invalid credentials' });
    } else {
      res.status(500).json({ error: 'Authentication failed' });
    }
  }
});

πŸ” Environment Variables

Create a .env file:

# Google OAuth
GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-xxx

# GitHub OAuth
GITHUB_CLIENT_ID=Iv1.xxx
GITHUB_CLIENT_SECRET=xxx

# Facebook OAuth
FACEBOOK_CLIENT_ID=xxx
FACEBOOK_CLIENT_SECRET=xxx

# Twitter OAuth
TWITTER_CLIENT_ID=xxx
TWITTER_CLIENT_SECRET=xxx

# LinkedIn OAuth
LINKEDIN_CLIENT_ID=xxx
LINKEDIN_CLIENT_SECRET=xxx

# Microsoft OAuth
MICROSOFT_CLIENT_ID=xxx
MICROSOFT_CLIENT_SECRET=xxx

# Apple Sign In
APPLE_CLIENT_ID=xxx
APPLE_CLIENT_SECRET=xxx

🎨 Custom Provider

You can create custom OAuth providers by extending the BaseOAuthProvider:

import { BaseOAuthProvider, OAuthUser } from 'multi-oauth';

class CustomOAuthProvider extends BaseOAuthProvider {
  getName(): string {
    return 'custom';
  }

  getAuthUrl(): string {
    return 'https://custom.com/oauth/authorize';
  }

  getTokenUrl(): string {
    return 'https://custom.com/oauth/token';
  }

  getUserProfileUrl(): string {
    return 'https://custom.com/api/user';
  }

  getDefaultScopes(): string[] {
    return ['read', 'email'];
  }

  normalizeUser(profile: any): OAuthUser {
    return {
      id: profile.id,
      name: profile.full_name,
      email: profile.email_address,
      avatar: profile.avatar_url,
      provider: 'custom',
      raw: profile
    };
  }
}

πŸ“Š TypeScript Types

All types are exported for your convenience:

import type {
  OAuthUser,
  OAuthConfig,
  ProviderConfig,
  ProviderName,
  OAuthRequest,
  TokenResponse
} from 'multi-oauth';

// Use types in your application
function saveUser(user: OAuthUser) {
  // Your code here
}

const config: OAuthConfig = {
  providers: {
    google: {
      clientId: 'xxx',
      clientSecret: 'xxx'
    }
  },
  redirectUri: 'http://localhost:3000/callback'
};

❓ FAQ

How do I get user's email?

Most providers return email by default. Some providers (like GitHub) might require additional scopes or API calls:

github: {
  clientId: 'xxx',
  clientSecret: 'xxx',
  scope: ['user:email'] // Request email access
}

Can I use this in production?

Yes! Easy OAuth is production-ready. Make sure to:

  • Use HTTPS in production
  • Store client secrets securely (use environment variables)
  • Implement proper session management
  • Handle errors appropriately

How do I handle state parameter for CSRF protection?

app.get('/login/:provider', (req, res) => {
  const state = generateRandomString(); // Your implementation
  req.session.oauthState = state;
  res.redirect(auth.url(req.params.provider, state));
});

app.get('/callback/:provider', async (req, res) => {
  // Verify state
  if (req.query.state !== req.session.oauthState) {
    return res.status(400).json({ error: 'Invalid state' });
  }
  
  const user = await auth.callback(req.params.provider, req);
  res.json(user);
});

Does it work with JavaScript (not TypeScript)?

Yes! The library is written in TypeScript but compiles to JavaScript. You can use it in any Node.js project:

const auth = require('multi-oauth').default;
// Use normally

How do I customize OAuth scopes?

auth.configure({
  providers: {
    google: {
      clientId: 'xxx',
      clientSecret: 'xxx',
      scope: ['openid', 'profile', 'email', 'https://www.googleapis.com/auth/calendar']
    }
  },
  redirectUri: 'http://localhost:3000/callback'
});

🀝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Commit your changes: git commit -am 'Add new feature'
  4. Push to the branch: git push origin feature/my-feature
  5. Submit a pull request

Development Setup

# Clone the repository
git clone https://github.com/zaghamabbas786/multi-oauth.git

# Install dependencies
npm install

# Build the project
npm run build

# Watch mode
npm run watch

πŸ“„ License

MIT Β© [Your Name]

🌟 Star Us!

If you find Easy OAuth useful, please give us a star on GitHub! ⭐

πŸ“š Related Projects

πŸ“ž Support


Made with ❀️ by developers, for developers.

Keywords: oauth, oauth2, authentication, google login, facebook login, github login, twitter login, linkedin login, apple login, microsoft login, social login, sso, single sign on, node.js authentication, express oauth, nextjs oauth, typescript oauth, simple oauth, easy authentication

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published