PHPackages                             jiripudil/otp - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. jiripudil/otp

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

jiripudil/otp
=============

Library that generates and verifies one-time passwords.

2.0.0(5mo ago)2825.4k↓12.2%31MITPHPPHP ^8.2CI passing

Since Dec 16Pushed 5mo ago2 watchersCompare

[ Source](https://github.com/jiripudil/otp)[ Packagist](https://packagist.org/packages/jiripudil/otp)[ GitHub Sponsors](https://github.com/jiripudil)[ RSS](/packages/jiripudil-otp/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (5)Versions (5)Used By (1)

One-Time Passwords in PHP
=========================

[](#one-time-passwords-in-php)

OTP is a library that generates and verifies One-Time Passwords conforming to the HOTP ([RFC 4226](https://datatracker.ietf.org/doc/html/rfc4226)) and TOTP ([RFC 6238](https://datatracker.ietf.org/doc/html/rfc6238)) algorithms. These one-time passwords are commonly used as a second factor during user authentication. In short, your application and the user's OTP application are both able to generate a number based on a shared secret. Whenever you need to authenticate the user, ask them to enter the code generated by their application and verify it with this library.

Installation and requirements
-----------------------------

[](#installation-and-requirements)

```
$ composer require jiripudil/otp
```

OTP requires PHP &gt;= 8.2.

Usage
-----

[](#usage)

The entrypoint of this library is the `JiriPudil\OTP\OTP` class:

```
$otp = new JiriPudil\OTP\OTP('My Application', $otpType);
```

It expects you to provide:

1. **The `$issuer` name.** This is often used by the end-user applications to distinguish OTPs for various services, and should thus clearly identify your application.
2. **An `$otp` type.** This library provides implementations for both HOTP and TOTP. See below for details.
3. **The hashing `$algorithm`.** This is optional and defaults to SHA-1. ⚠ Please be aware that some end-user implementations such as Google Authenticator only support this algorithm.

### Time-based OTP

[](#time-based-otp)

The `JiriPudil\OTP\TimeBasedOtp` class implements the TOTP according to RFC 6238 and it is perhaps the most commonly used type of OTPs. It generates a code in a fixed-time interval.

The constructor expects you to provide an implementation of `Psr\Clock\ClockInterface`.

Using time-based OTPs requires the clocks on your server and in the user's application to be in sync. To compensate for the possible differences between the times, you can provide an optional `tolerance` which determines how many time periods before and after the current time should be considered valid. It defaults to 1, which means that the code for the previous and the next period will pass the verification.

You can also configure the time interval which defaults to 30 seconds. ⚠ While the interval can be changed, again, some end-user implementations do not support different intervals than the default.

```
$otpType = new JiriPudil\OTP\TimeBasedOTP($clock, tolerance: 1, timeStep: 30);
```

### HMAC-based OTP

[](#hmac-based-otp)

The `JiriPudil\OTP\HmacBasedOTP` class implements the HOTP according to RFC 4226. Instead of time, this type of OTP relies on a counter that is kept both by the user's application and by the server. That's why the class requires you to provide an implementation of a `JiriPudil\OTP\HmacBasedOTP\CounterRepository` which retrieves and updates the counter for a given `$account`. Your implementation should operate upon some persistent storage such as a relational database.

The user's counter is incremented every time they request a new code, while the server's counter is only incremented after a successful verification attempt. To account for a possible desynchronization of the counter value, you can configure a `$lookAhead` parameter which tells this library to check several subsequent counter values. This parameter defaults to 3.

```
$otpType = new JiriPudil\OTP\HmacBasedOTP($myCounterRepository, lookAhead: 3);
```

Setting up 2FA
--------------

[](#setting-up-2fa)

First of all, you need to generate a random secret. The `OTP` class provides a method for that which makes sure that the secret is long enough for the configured hashing algorithm:

```
$secret = $otp->generateSecret();
```

The secret must be unique to the user, and should therefore be stored somewhere with other user data – preferably encrypted because it is a very sensitive value:

```
$myUserRepository->encryptAndSaveOtpSecret($myUser, $secret);
```

A second value that is tied to the user is the account name: this should be a value that uniquely identifies the user in your application, e.g. their email address. These two pieces of information are exposed to this OTP library in the form of `JiriPudil\OTP\Account\AccountDescriptor`. There is a handy simple implementation in `JiriPudil\OTP\Account\SimpleAccountDescriptor` which should be sufficient for most cases:

```
$account = new SimpleAccountDescriptor($myUser->getEmailAddress(), $myUser->getOtpSecret());
```

You can then call `getProvisioningUri` for this `$account` to retrieve a URI that can be used to set up the end-user OTP application. You can optionally specify the number of digits the generated code should have – this can be a value between 6 and 8 inclusive, and it defaults to 6 which is the most commonly used value:

```
$uri = $otp->getProvisioningUri($account, digits: 6);
```

This URI is usually displayed in the form of a QR code that the user application can scan. Alternatively, you can directly display the Base32-encoded secret for the user to type or copy into their application:

```
$encodedSecret = $account->getSecret()->asBase32();
```

Verification
------------

[](#verification)

Once the user has set up the account in their OTP application, you can ask them to enter the code and easily verify that the setup is correct:

```
if ($otp->verify($account, $enteredCode, expectedDigits: 6)) {
	// successfully verified
} else {
	// incorrect code
}
```

At this point, you should generate and display a set of recovery codes in case the user loses access to their OTP application. After that, you can consider the user's OTP setup in your application finished, and you can start requiring the code as a second factor during their authentication.

Client usage
------------

[](#client-usage)

This package can also be used as an OTP client:

```
$code = $otp->generate($account, digits: 6);
```

###  Health Score

49

—

FairBetter than 95% of packages

Maintenance70

Regular maintenance activity

Popularity38

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~358 days

Total

4

Last Release

174d ago

Major Versions

1.0.2 → 2.0.02025-11-25

PHP version history (2 changes)1.0.0PHP ^8.1

2.0.0PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/0fa15809b1f4544a0696a3f8e0d9719014242c0f7de639b12919eaedfd213cfe?d=identicon)[jiripudil](/maintainers/jiripudil)

---

Top Contributors

[![jiripudil](https://avatars.githubusercontent.com/u/1042159?v=4)](https://github.com/jiripudil "jiripudil (11 commits)")

---

Tags

authenticationhacktoberfesthotpotpphptotphotptotpsecurityAuthentication2fa

###  Code Quality

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/jiripudil-otp/health.svg)

```
[![Health](https://phpackages.com/badges/jiripudil-otp/health.svg)](https://phpackages.com/packages/jiripudil-otp)
```

###  Alternatives

[spomky-labs/otphp

A PHP library for generating one time passwords according to RFC 4226 (HOTP Algorithm) and the RFC 6238 (TOTP Algorithm) and compatible with Google Authenticator

1.5k46.1M119](/packages/spomky-labs-otphp)[paragonie/multi-factor

Vendor-agnostic two-factor authentication library

142195.5k2](/packages/paragonie-multi-factor)[chillerlan/php-authenticator

A generator for counter- and time based 2-factor authentication codes (Google Authenticator). PHP 8.2+

58119.1k2](/packages/chillerlan-php-authenticator)[2amigos/2fa-library

2 Factor Authentication (2FA) library

34367.1k7](/packages/2amigos-2fa-library)[kelunik/two-factor

Two factor authentication.

371.9k1](/packages/kelunik-two-factor)[remotemerge/totp-php

Lightweight, fast, and secure TOTP (2FA) authentication library for PHP — battle tested, dependency free, and ready for enterprise integration.

2010.2k](/packages/remotemerge-totp-php)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
