Deploy once, authenticate every project. Multi-tenant identity API with OAuth, 2FA, and complete account management.
Live Demo | API Docs | Features | Quick Start
AuthKit is a self-hosted, multi-tenant identity API designed to eliminate repetitive auth work across projects. Deploy it once, then connect any application as a tenant — each gets its own isolated user base, API key, and full-featured authentication system.
The idea: Instead of rewriting authentication for every side project, I built AuthKit to be my personal Auth0,clerk/Firebase Auth — a single backend that powers all my apps.
authentication oauth 2fa multi-tenant typescript express postgresql docker gcp cloud-run github-actions ci-cd jwt security
| Category | Stack |
|---|---|
| Runtime | Node.js 24 |
| Framework | Express 5.x |
| Language | TypeScript (strict mode) |
| Database | PostgreSQL 17 |
| Testing | Jest + Supertest |
| Security | Passport.js, JWT, bcrypt, Helmet |
| Resend | |
| Image Upload | Cloudinary |
| Containerization | Docker |
| CI/CD | GitHub Actions |
| Deployment | Google Cloud Run |
- Email/password registration and login
- Secure logout with token revocation
- OAuth 2.0 (Google & GitHub)
- JWT access tokens (15min) + refresh token rotation (7d)
- httpOnly cookies for XSS protection
- Email verification on registration
- Resend verification email
- Forgot password & reset flow
- Email change with re-verification
- Two-Factor Authentication (TOTP) with backup codes
- Rate limiting (100/min global, 10/min auth)
- bcrypt password hashing (12 rounds)
- SQL injection prevention (parameterized queries)
- CSRF-protected OAuth flows (state tokens)
- Profile updates (name, avatar via Cloudinary)
- Change password (local accounts only)
- Soft account deletion (30-day restore window)
- Account restoration via email token
- Each application registers as a tenant
- Per-tenant API key authentication
- Fully isolated user bases per tenant
- Node.js v24+
- Docker & Docker Compose
- PostgreSQL (via Docker or external)
# Clone the repo
git clone https://github.com/juma-paul/authkit.git
cd authkit
# Install dependencies
npm install
# Copy environment variables
cp .env.example .env.development
# Edit .env.development with your values
# Start infrastructure (PostgreSQL)
docker-compose up -d
# Run database migrations
# inside infrastructure/database
psql "DATABASE_URL" -f schema.sql
# Start development server
npm run devcurl http://localhost:3002/health
# Response: {"status":"ok","environment":"development"}npm run dev # Start with hot reload
npm test # Run tests
npm run test:watch # Watch mode
npm run build # Build for production
npm start # Run production builddocker build -t authkit .
docker run -p 3002:3002 --env-file .env authkitCopy .env.example to .env.development and configure:
| Category | Variables |
|---|---|
| Server | PORT, NODE_ENV, APP_URL, API_URL |
| Database | DATABASE_URL |
| Auth | JWT_SECRET, JWT_REFRESH_SECRET, expiry settings |
| OAuth | Google & GitHub client IDs, secrets, callbacks |
| Services | Resend API key, Cloudinary credentials |
| Admin | ADMIN_SECRET |
See .env.example for complete list with descriptions.
Full API documentation: API_DOCS.md
https://your-api.com/api/v1
- All endpoints require
X-API-Keyheader with your tenant API key - Protected endpoints use
accessTokencookie (set automatically on login)
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # With coverage reportLive Demo: authkit-demo-six.vercel.app
Video Walkthrough:
Click to watch the full demo on YouTube
Reference Client: AuthKit Demo — Production-ready Next.js frontend
- Architecture Design — Clean separation: controllers for business logic, middleware for cross-cutting concerns, services for external integrations
- Security First — Implemented httpOnly cookies, JWT rotation, bcrypt hashing, and rate limiting from day one
- Multi-Tenancy — Designed database schema with tenant isolation using API keys and composite unique constraints
- OAuth Integration — Added Google and GitHub using Passport.js with CSRF-protected state tokens
- Testing — Built comprehensive test suite with Jest + Supertest, mocking external services
- Token Refresh Race Conditions — Frontend interceptors need request queuing during refresh to avoid multiple refresh calls
- 401 vs 400 Semantics — Using specific error codes (
TOKEN_EXPIREDvsUNAUTHORIZED) enables smarter client-side handling - Soft Delete UX — 30-day restore windows require clear user communication and email-based recovery flows
- OAuth State Tokens — Essential for preventing CSRF attacks in OAuth flows
- Add Redis for token blacklisting and session management
- Implement account lockout after N failed login attempts
- Add WebAuthn/passkey support
- Structured logging with Winston/Pino
- Request tracing with correlation IDs
- Prometheus metrics endpoint
- GraphQL API alongside REST
src/
├── config/ # Environment, database, passport
├── controllers/ # Request handlers
├── middleware/ # Auth, error handling, tenant
├── routes/ # API route definitions
├── services/ # Email service
├── utils/ # Tokens, cookies, response helpers
├── errors/ # Custom error classes
├── validators/ # Zod validation schemas
├── constants/ # Error messages, configs
└── tests/ # Jest test suites
- Fork the repository
- Create feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
- TypeScript strict mode
- ESLint + Prettier
- Conventional commits
- AuthKit Demo — Reference frontend client built with Next.js, demonstrating full integration with AuthKit.
This project is open source and available under the MIT License.
