A drop-in authentication API for personal projects — registration, login, OAuth (Google + GitHub), email verification, password reset, and profile management. TypeScript, Express 5, Mongoose 9. Security-first, self-hosted.
git clone https://github.com/NehanAhmed/cred.git
cd cred
pnpm install
cp .env.example .env # then fill in secrets
pnpm devAll required variables are listed in .env.example. Key ones:
| Variable | Description |
|---|---|
MONGO_URI |
MongoDB connection string |
JWT_SECRET |
Secret for signing JSON Web Tokens |
CLIENT_URL |
Frontend URL (e.g. http://localhost:5173) |
BACKEND_URL |
Backend URL (e.g. http://localhost:3000) |
CORS_ORIGIN |
Allowed CORS origin (typically same as CLIENT_URL) |
GOOGLE_OAUTH_CLIENT_ID |
Google OAuth app ID |
GOOGLE_OAUTH_CLIENT_SECRET |
Google OAuth app secret |
GITHUB_OAUTH_CLIENT_ID |
GitHub OAuth app ID |
GITHUB_OAUTH_CLIENT_SECRET |
GitHub OAuth app secret |
SMTP is optional — dev mode uses Ethereal (preview URLs logged to console). For production, provide SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, SMTP_FROM.
| Layer | Technology |
|---|---|
| Runtime | Node.js ≥18 — ts-node-dev (hot reload) |
| Language | TypeScript 6 (strict, ES2022, CommonJS) |
| Web Framework | Express 5 |
| Database | MongoDB via Mongoose 9 |
| Auth | bcryptjs + jsonwebtoken (httpOnly cookies) |
| OAuth | Passport (Google + GitHub) |
| Validation | Zod 4 |
| Rate Limiting | express-rate-limit (per-endpoint + global) |
| Security | helmet, cookie-parser (httpOnly, sameSite, secure) |
| Nodemailer + Ethereal (dev) / SMTP (prod) | |
| Package Manager | pnpm 10 |
| Area | Capabilities |
|---|---|
| Registration | Username, email, password, bio, phone, gender. Zod-validated. Email verification required before login. |
| Login / Logout | Email or username. httpOnly JWT cookie (strict sameSite, secure in production). |
| OAuth | Google + GitHub. Auto-links to existing accounts by email. Generates unique usernames on collision. |
| Verification, forgot password, reset password. Ethereal in dev, SMTP in prod. | |
| Profile | Get, update (username, bio, phone, gender), change password, delete account. |
| Security | bcrypt (10 rounds), rate limiting per endpoint, helmet headers, 10kb body limit, generic login errors (no user enumeration), startup env validation. |
All routes are prefixed with /api.
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/api/auth |
No | Register |
POST |
/api/auth/login |
No | Log in (returns JWT cookie) |
POST |
/api/auth/logout |
Yes | Clear JWT cookie |
GET |
/api/auth/verify-email/:token |
No | Verify email (redirects to frontend) |
POST |
/api/auth/forgot-password |
No | Send password reset email |
POST |
/api/auth/reset-password/:token |
No | Reset password |
GET |
/api/auth/google |
No | Initiate Google OAuth |
GET |
/api/auth/google/callback |
No | Google OAuth callback |
GET |
/api/auth/github |
No | Initiate GitHub OAuth |
GET |
/api/auth/github/callback |
No | GitHub OAuth callback |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/profile/me |
Yes | Get profile |
PUT |
/api/profile/me |
Yes | Update profile |
DELETE |
/api/profile/me |
Yes | Delete account |
POST |
/api/profile/me/change-password |
Yes | Change password |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/health |
No | App + DB health check |
115 tests across 7 suites. In-memory MongoDB (mongodb-memory-server), supertest for HTTP, email helpers mocked.
pnpm test # run all
pnpm test:coverage # with coverage report| Suite | Tests |
|---|---|
| Auth (register, login, logout, refresh, verify-email) | 27 |
| Auth email (forgot-password, reset-password) | 11 |
| Profile (get, update, delete, change-password) | 26 |
| OAuth (Google + GitHub init + callback) | 15 |
| Health (app + DB status) | 10 |
| Audit (session logging, pagination) | 22 |
| Rate limiters (all 8 limiters) | 4 |
MIT. See LICENSE.
Copyright © 2026 Nehan Ahmed
Contributions welcome. Open an issue or pull request at github.com/NehanAhmed/cred.
