atozas-auth-kit-express
v1.0.0
Published
Production-ready Express authentication with Google OAuth and Email OTP
Downloads
9
Maintainers
Readme
atozas-auth-kit-express
Production-ready Express authentication with Google OAuth and Email OTP. Zero passwords, maximum security.
Features
- 🔐 Google OAuth - Sign in with Google using
google-auth-library - 📧 Email OTP - Passwordless login with 6-digit codes
- 🔒 JWT Tokens - Access tokens (15min) + HTTP-only refresh cookies (30d)
- 🛡️ Rate Limiting - Built-in OTP request rate limiting
- 📦 TypeScript - Full type definitions included
- 🚀 Zero Config - Sensible defaults, fully customizable
- 🔌 Pluggable - Bring your own email service (Nodemailer, SendGrid, etc.)
Installation
npm install atozas-auth-kit-expressQuick Start
import express from 'express';
import mongoose from 'mongoose';
import cookieParser from 'cookie-parser';
import { createAuthRouter, createRequireAuth } from 'atozas-auth-kit-express';
const app = express();
// Middleware
app.use(express.json());
app.use(cookieParser());
// Connect to MongoDB
await mongoose.connect(process.env.MONGODB_URI!);
// Setup auth router
const authRouter = createAuthRouter({
googleClientId: process.env.GOOGLE_CLIENT_ID!,
jwtSecret: process.env.JWT_SECRET!,
jwtRefreshSecret: process.env.JWT_REFRESH_SECRET!,
// Email adapter - use any service you want
sendEmailOtp: async (to, otp) => {
// Example with Nodemailer
await transporter.sendMail({
from: '[email protected]',
to,
subject: 'Your Login Code',
text: `Your OTP is: ${otp}`,
});
},
});
app.use('/api/auth', authRouter);
// Protected route example
const requireAuth = createRequireAuth({
googleClientId: process.env.GOOGLE_CLIENT_ID!,
jwtSecret: process.env.JWT_SECRET!,
jwtRefreshSecret: process.env.JWT_REFRESH_SECRET!,
sendEmailOtp: async () => {}, // Not needed for middleware
});
app.get('/api/protected', requireAuth, (req, res) => {
res.json({ user: req.user });
});
app.listen(3000);API Endpoints
The auth router provides these endpoints:
POST /google
Login with Google OAuth
Request:
{
"credential": "google_id_token"
}Response:
{
"success": true,
"accessToken": "jwt_token",
"user": {
"id": "user_id",
"email": "[email protected]",
"name": "John Doe",
"picture": "https://...",
"provider": "google"
}
}POST /email/send-otp
Send OTP to email
Request:
{
"email": "[email protected]"
}Response:
{
"success": true,
"message": "OTP sent to email",
"expiresIn": 300
}POST /email/verify-otp
Verify OTP and login
Request:
{
"email": "[email protected]",
"otp": "123456"
}Response:
{
"success": true,
"accessToken": "jwt_token",
"user": {
"id": "user_id",
"email": "[email protected]",
"provider": "email"
}
}POST /refresh
Refresh access token (uses refresh token from cookie)
Response:
{
"success": true,
"accessToken": "new_jwt_token"
}GET /me
Get current user (requires authentication)
Headers:
Authorization: Bearer {accessToken}Response:
{
"success": true,
"user": {
"id": "user_id",
"email": "[email protected]",
"name": "John Doe",
"provider": "google"
}
}POST /logout
Logout user (clears refresh token cookie)
Response:
{
"success": true,
"message": "Logged out successfully"
}Configuration
interface AuthConfig {
// Required
googleClientId: string;
jwtSecret: string;
jwtRefreshSecret: string;
sendEmailOtp: (to: string, otp: string) => Promise<void>;
// Optional
accessTokenExpiry?: string; // default: '15m'
refreshTokenExpiry?: string; // default: '30d'
otpExpiry?: number; // minutes, default: 5
otpLength?: number; // default: 6
otpRateLimit?: {
maxAttempts: number; // default: 3
windowMs: number; // default: 900000 (15 min)
};
cookieOptions?: {
httpOnly?: boolean; // default: true
secure?: boolean; // default: true in production
sameSite?: 'strict' | 'lax' | 'none'; // default: 'lax'
domain?: string;
path?: string;
};
frontendUrl?: string;
}Middleware
requireAuth
Protects routes by verifying JWT access token.
import { createRequireAuth } from 'atozas-auth-kit-express';
const requireAuth = createRequireAuth(config);
app.get('/api/protected', requireAuth, (req, res) => {
// req.user is populated
res.json({ user: req.user });
});Models
User Model
{
email: string;
name?: string;
picture?: string;
provider: 'google' | 'email';
googleId?: string;
createdAt: Date;
updatedAt: Date;
}OTP Model
{
email: string;
otp: string; // hashed
expiresAt: Date;
used: boolean;
ipAddress?: string;
createdAt: Date;
}Email Adapters
Nodemailer Example
import nodemailer from 'nodemailer';
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: 587,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
const authRouter = createAuthRouter({
// ...other config
sendEmailOtp: async (to, otp) => {
await transporter.sendMail({
from: '"Your App" <[email protected]>',
to,
subject: 'Your Login Code',
html: `
<h1>Your login code</h1>
<p>Your OTP is: <strong>${otp}</strong></p>
<p>This code expires in 5 minutes.</p>
`,
});
},
});AWS SES Example
import { SESClient, SendEmailCommand } from '@aws-sdk/client-ses';
const ses = new SESClient({ region: 'us-east-1' });
const authRouter = createAuthRouter({
// ...other config
sendEmailOtp: async (to, otp) => {
await ses.send(new SendEmailCommand({
Source: '[email protected]',
Destination: { ToAddresses: [to] },
Message: {
Subject: { Data: 'Your Login Code' },
Body: {
Html: { Data: `<p>Your OTP is: <strong>${otp}</strong></p>` },
},
},
}));
},
});TypeScript
Full TypeScript support with exported types:
import type {
AuthConfig,
AuthRequest,
UserPayload,
TokenPayload,
UserDocument,
OtpDocument,
} from 'atozas-auth-kit-express';License
MIT
