npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

create-express-auth-app

v1.0.0

Published

Scaffold a ready-to-run Node/Express JWT authentication backend (MongoDB or PostgreSQL, JavaScript or TypeScript, optional Google OAuth and TOTP 2FA) with one command.

Readme

create-express-auth-app

Scaffold a production-style Node.js + Express JWT authentication backend in one command.

npm version npm downloads npm total downloads Node.js License TypeScript GitHub stars GitHub issues Last commit PRs welcome

Stop rewriting the same login, refresh-token, email-verification and password-reset code for every project. create-express-auth-app generates a complete, working auth backend into a folder you own: routes, controllers, services, models, middleware, validation, configuration and a ready-to-use .env.

npx create-express-auth-app my-app

Features

  • Two databases: MongoDB (Mongoose) or PostgreSQL (Drizzle ORM)
  • TypeScript or JavaScript: pick your language; the JavaScript output is generated from the same source, so both stay identical in behavior
  • Email verification: a clickable link, or a 6-digit code
  • Two-factor authentication (optional): TOTP for authenticator apps such as Google Authenticator or Authy, with QR-code setup
  • Google sign-in (optional): verifies Google ID tokens server-side
  • Secure sessions: short-lived access token plus rotating refresh token, both in httpOnly, SameSite=Strict cookies, never exposed to browser JavaScript
  • Safe by default: bcrypt-hashed passwords, hashed refresh and verification tokens at rest, rate-limited login and reset endpoints, Zod input validation, no user-enumeration leaks
  • Works out of the box: secrets are generated for you, and emails are printed to the console when SMTP isn't configured, so you can test the whole flow locally
  • You own the code: the generated project has no runtime dependency on this package

Requirements

  • Node.js 20.12 or newer
  • A running MongoDB or PostgreSQL instance for the database you choose

Quick start

npx create-express-auth-app my-app
cd my-app

Answer the prompts, then:

# PostgreSQL only: create and apply the tables
npm run db:generate
npm run db:migrate

npm run dev

The API is now running on http://localhost:3000. Check it with:

curl http://localhost:3000/api/health

MongoDB projects need no migration step.

Prompts

| Prompt | Options | Default | | ------------------------ | ----------------------------- | ------------- | | Project directory | any path | required | | Project name | valid npm package name | folder name | | Package manager | npm, pnpm, yarn | npm | | Language | TypeScript, JavaScript | TypeScript | | Database | MongoDB, PostgreSQL | MongoDB | | Email verification | link, 6-digit code | link | | Google OAuth | yes / no | no | | Two-factor auth (TOTP) | yes / no | no | | Connection string | MongoDB URI or PostgreSQL URL | local default | | Install dependencies now | yes / no | yes |

Non-interactive usage

Every prompt has a flag, which makes the CLI usable in scripts and CI.

npx create-express-auth-app my-app \
  --db postgres --lang ts --verify code --google --2fa --pm pnpm --yes

| Flag | Values | Description | | -------------------------- | --------------------- | ------------------------------------------------------ | | --db | mongo, postgres | Database | | --lang | ts, js | Output language | | --verify | link, code | Email verification method | | --google / --no-google | | Include or skip Google OAuth | | --2fa / --no-2fa | | Include or skip TOTP two-factor auth | | --pm | npm, pnpm, yarn | Package manager used to install | | --no-install | | Skip dependency installation | | --yes | | Skip all prompts; unset options use the defaults above |

API reference

Base path: /api

| Method | Endpoint | Auth | Description | | ------- | ----------------------------- | -------- | ----------------------------------------------------------------- | | GET | /health | | Health check | | POST | /auth/register | | Create an account and send a verification message | | GET | /auth/verify-email/:token | | Verify email (link mode); logs the user in | | POST | /auth/verify-email | | Verify email with { email, code } (code mode); logs the user in | | POST | /auth/resend-verification | | Send a new verification message | | POST | /auth/login | | Log in; sets cookies | | POST | /auth/refresh-token | cookie | Rotate the refresh token and issue a new access token | | POST | /auth/logout | required | Log out and revoke refresh tokens | | POST | /auth/forgot-password | | Send a password reset link | | GET | /auth/reset-password/:token | | Check that a reset link is still valid | | PATCH | /auth/reset-password/:token | | Set a new password | | GET | /users/me | required | Get the current user's profile | | PATCH | /users/me | required | Update name, phone and address | | POST | /auth/google | | Log in with a Google ID token (Google option) | | POST | /auth/2fa/setup | required | Generate a secret and QR code (2FA option) | | POST | /auth/2fa/enable | required | Confirm setup with a 6-digit code (2FA option) | | POST | /auth/2fa/disable | required | Turn 2FA off; needs a current { code } (2FA option) | | POST | /auth/2fa/verify-login | | Finish a 2FA login with { pendingToken, code } (2FA option) |

Verification link and code modes each expose only their own verify-email route.

Example

# Register
curl -X POST http://localhost:3000/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"name":"Ada","email":"[email protected]","password":"correct-horse-battery"}'

# Log in and keep the cookies
curl -i -c cookies.txt -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","password":"correct-horse-battery"}'

# Call a protected route with the cookies
curl -b cookies.txt http://localhost:3000/api/users/me

With two-factor auth enabled for a user, login returns { "twoFactorRequired": true, "pendingToken": "..." } instead of cookies. Send that token and a code from the authenticator app to /auth/2fa/verify-login to finish logging in.

What gets generated

my-app/
├── src/
│   ├── app.ts              Express app, CORS, error handler
│   ├── index.ts            Server entry point
│   ├── constants/          Roles, cookie names, token lifetimes
│   ├── configs/            Cookie options, database connection
│   ├── models/             Mongoose models          (MongoDB)
│   ├── db/schema.ts        Drizzle tables           (PostgreSQL)
│   ├── schemas/            Zod request validation
│   ├── middlewares/        JWT auth, role guard, rate limiters
│   ├── controllers/        Request handlers
│   ├── services/           Business logic and database access
│   ├── routes/             Route definitions
│   └── utils/              Token helpers, HTTP error class
├── drizzle.config.ts       drizzle-kit config       (PostgreSQL)
├── .env                    Generated, with random secrets (git-ignored)
├── .env.example            Same keys without values, safe to commit
├── .gitignore
├── tsconfig.json           TypeScript only
├── package.json
└── README.md               Project-specific instructions

Environment variables

| Variable | Purpose | | --------------------------------------------------------------- | ------------------------------------------------------------------------- | | PORT | Server port (default 3000) | | NODE_ENV | production turns on the Secure cookie flag | | MONGO_URI / DATABASE_URL | Database connection string | | CLIENT_URL | Frontend origin allowed by CORS | | CLIENT_BASE_URL | Base URL used in email links | | SALT_ROUNDS | bcrypt cost factor || JWT_ACCESS_SECRET, JWT_REFRESH_SECRET | Token signing secrets | | REFRESH_TOKEN_HASH_SECRET, EMAIL_TOKEN_HASH_SECRET | Keys for hashing stored tokens | | SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, SMTP_FROM | Outgoing email. Leave blank in development to print emails to the console | | GOOGLE_CLIENT_ID | Only with the Google option |

The four secrets are filled with random values when the project is created.

Security notes

  • Access tokens last 15 minutes and refresh tokens 10 days. Refresh tokens are rotated on every use, and only a hash of each is stored.
  • Rate limits per IP: login 5 per 15 minutes; registration 5 per hour; password reset and resend-verification 3 per hour each; code-based email verification and 2FA codes 10 per 15 minutes.
  • Every JWT carries a purpose claim that is checked on verification, so a 2FA pending token can't be used as an access token.
  • Disabling 2FA needs a current authenticator code, not just a session.
  • Google sign-in only accepts accounts whose email Google has verified.
  • Passwords are always hashed before they are saved, through a single code path in each database variant.
  • Registration, password reset and resend-verification responses are identical whether or not the account exists.
  • The server refuses to start if CLIENT_URL or any of the secrets are missing.
  • Cookies are httpOnly and SameSite=Strict, so tokens are not readable from browser JavaScript.

Known simplifications

These are deliberate defaults you can change in the generated code:

  • Logging out signs the user out of every device, not just the current one.
  • One active refresh token per user, rotated in place, rather than one per session.
  • PostgreSQL does not delete expired token rows automatically. Every lookup checks the expiry time, so expired tokens are never accepted, but old rows stay until you prune them (for example with a scheduled DELETE ... WHERE expires_at < now()). MongoDB removes them itself with TTL indexes.
  • Roles are stored (customer, staff, admin) and a role guard middleware is included, but no admin or staff routes are generated.

FAQ

Does my generated project depend on create-express-auth-app? No. It only uses regular packages such as Express, Zod, and Mongoose or Drizzle. You can delete this CLI after scaffolding.

Can I use my own SMTP provider? Yes. Fill in the SMTP_* variables. Any provider that supports SMTP works, such as Resend, Postmark, SendGrid or Gmail app passwords.

Why does the console show links instead of sending email? With no SMTP settings, the app prints verification links and codes to the console so you can develop without an email account.

Can I add the Google or 2FA option later? Not through the CLI. Scaffold a new project with the option on and copy the extra files across.

Contributing

Issues and pull requests are welcome at github.com/mrrauf99/create-express-auth-app.

git clone https://github.com/mrrauf99/create-express-auth-app.git
cd create-express-auth-app
npm install
npm link
create-express-auth-app ../scratch-app
npm test                 # scaffolds every option combination and checks the output
TYPECHECK=1 npm test     # also installs deps and type-checks the generated TypeScript (slow)

To release, bump version in package.json, update CHANGELOG.md, then publish a GitHub release tagged v<version> (for example v1.0.1). The Release workflow reruns CI and publishes to npm with provenance. Versions with a pre-release suffix such as 1.1.0-beta.1 go to the next tag instead of latest.

Templates live in templates/ and are written once in TypeScript: shared/ is always included, then one database (mongo/ or postgres/), one verification method (verify-link/ or verify-code/), and the optional google-oauth/ and two-factor/ layers. bin/lib/scaffold.js combines the selected layers and, for JavaScript output, removes the type annotations with esbuild.

License

MIT