notp

Zero-dependency Node.js library for generating and verifying HOTP and TOTP one-time passwords compatible with Google Authenticator.

Library
npm
v2.0.3
690stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
41/100Fair
Development Activity0
Maintenance20
Community64
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
53/100Fair
Architecture55
Code Quality42
Innovation58
Learning Curve55

notp is a lightweight, dependency-free Node.js library for generating and verifying one-time passwords using the HOTP (RFC 4226) and TOTP (RFC 6238) algorithms. It exposes a small, synchronous API — hotp.gen/hotp.verify and totp.gen/totp.verify — that developers wire into login flows to add second-factor authentication compatible with apps like Google Authenticator.

Under the hood it computes an HMAC-SHA1 digest over a counter value, truncates it per the RFC spec, and compares codes across a configurable window to tolerate clock or counter drift between client and server. Because it has zero runtime dependencies and performs no I/O, it’s easy to audit and safe to drop into any Node codebase that needs standards-compliant one-time-password generation without pulling in a larger auth framework.

What You Get

  • A synchronous hotp.gen/hotp.verify pair implementing counter-based one-time passwords per RFC 4226.
  • A synchronous totp.gen/totp.verify pair implementing time-based one-time passwords per RFC 6238, layered directly on top of the HOTP implementation.
  • Configurable verification windows (window, counter, time) to tolerate clock drift or missed counter increments between client and server.
  • Zero runtime dependencies — the entire library is a single file built on Node’s built-in crypto module.

Common Use Cases

  • Adding a second authentication factor to a login flow, storing a per-user secret key and verifying user-submitted TOTP codes.
  • Generating a base32-encoded secret and QR code URI for enrollment in Google Authenticator or another compatible authenticator app.
  • Building custom two-factor authentication middleware for an existing Node.js auth system without adopting a full auth framework.
  • Implementing counter-based HOTP for hardware tokens or offline devices where a synchronized clock isn’t available.

Under The Hood

Architecture The library is a single file (index.js) exporting two flat objects, hotp and totp, each with gen and verify functions; totp.verify/gen simply derive a counter from the current time step and delegate to the equivalent hotp function, so there is no layered module structure beyond this thin composition — a reasonable shape for a library this small, but it means the two algorithms share no abstraction beyond a shared counter parameter.

Tech Stack notp has zero runtime dependencies and relies entirely on Node’s built-in crypto module (createHmac with sha1) for the cryptographic core; its devDependencies (mocha for tests, thirty-two for base32 encoding in the example script) are not required at runtime, and the package targets any Node version above v0.6.0 with no build step or bundler involved.

Code Quality A mocha test suite exercises both algorithms against the official RFC 4226 and RFC 6238 test vectors, which gives real confidence in correctness, but the test file’s comments show clear leftover artifacts from a careless find-and-replace (e.g. “HOTtoken”, “counterount”), several test-loop variables are declared without var (implicit globals), and the source still uses the deprecated new Buffer() constructor instead of Buffer.from(); there is no linter, no CI configuration beyond a now-defunct Travis badge, and no type definitions.

API Design The public surface is intentionally tiny — four functions across two namespaces, each taking a token/key/options triple — which makes basic usage nearly boilerplate-free, and the RFC-standard opt.window/opt.counter/opt.time options are consistently named across both algorithms; the tradeoff is that all inputs and outputs are untyped, error states are represented only as null rather than descriptive errors, and there is a single narrative example file rather than broader usage documentation.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search