OTPHP

A PHP library for generating TOTP and HOTP one-time passwords per RFC 4226 and RFC 6238

Library
Composer
v11.5.0
1,486stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
76/100Good
Development Activity68
Maintenance68
Community80
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
76/100Good
Architecture80
Code Quality78
Innovation72
Learning Curve75

OTPHP is a PHP library that implements one-time password generation according to RFC 4226 (HOTP, counter-based) and RFC 6238 (TOTP, time-based). It is fully compatible with Google Authenticator, FreeOTP, and other standard authenticator apps, making it a drop-in choice for adding two-factor authentication to PHP applications.

The library exposes a small, focused API centered on the TOTP and HOTP classes, both implementing a shared OTP interface. It supports generating provisioning URIs for QR code enrollment, customizing digest algorithms, digit counts, and periods/counters, and integrates with PSR-20 clocks for deterministic time handling in tests and distributed systems.

What You Get

  • TOTP (time-based) and HOTP (counter-based) classes implementing RFC 6238 and RFC 4226
  • Provisioning URI generation for QR-code enrollment in authenticator apps
  • PSR-20 ClockInterface integration for deterministic, testable time handling
  • Configurable digest algorithm, digit count, period, and secret size
  • A Factory class for reconstructing OTP objects from stored provisioning URIs

Common Use Cases

  • Adding two-factor authentication (2FA) enrollment and verification to a PHP web app
  • Generating QR codes so users can scan a secret into Google Authenticator or FreeOTP
  • Verifying submitted OTP codes against a stored secret with configurable time drift windows
  • Persisting and reloading OTP configuration via provisioning URIs in a user’s account record

Under The Hood

Architecture: The library is organized around a small class hierarchy: an abstract OTP base class (515 lines) implements shared secret/digest/digits logic and provisioning-URI parsing, while TOTP and HOTP extend it with time-based and counter-based generation semantics respectively, each guarded by an interface (TOTPInterface, HOTPInterface) for consumer-side type safety. A Factory class handles reconstructing OTP instances from stored provisioning URIs, and Url.php centralizes URI parsing/building so both OTP types share one implementation. Time is abstracted through PSR-20’s ClockInterface, with an InternalClock fallback used only when no clock is injected (with a deprecation notice steering callers toward explicit clock injection ahead of a planned v12 breaking change).

Tech Stack: Pure PHP 8.1+ with no runtime framework dependency; declared dependencies are paragonie/constant_time_encoding (for constant-time base32 handling, avoiding timing side-channels), psr/clock (the PSR-20 interface), and symfony/deprecation-contracts (for structured deprecation notices). The package uses strict_types declarations throughout, PSR-4 autoloading, and Composer’s allow-plugins config for PHPStan and Infection tooling used in CI.

Code Quality: The tests/ directory includes dedicated HOTPTest, TOTPTest, and FactoryTest suites plus a ClockMock helper for deterministic time-based assertions, indicating the time-sensitive TOTP logic is directly covered rather than left to manual QA. Source files are compact (515 lines for the largest, OTP.php) and consistently typed with readonly properties and declare(strict_types=1), and the library uses dedicated exception classes under src/Exception/ rather than generic exceptions, so callers can catch specific failure modes (e.g. invalid parameters) distinctly.

API Design: The public API favors static factory methods (TOTP::generate(), TOTP::createFromSecret(), TOTP::create()) over public constructors, keeping object construction consistent and discoverable. Secret handling, provisioning URI generation, and verification are exposed as simple method calls with sensible defaults (30-second period, 6 digits, SHA1 digest) that match Google Authenticator’s expectations out of the box, while still allowing every parameter to be overridden for non-default authenticator apps.

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