PHPackages                             chillerlan/php-authenticator - 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. chillerlan/php-authenticator

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

chillerlan/php-authenticator
============================

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

6.0.0(1mo ago)58119.1k—6.6%22MITPHPPHP ^8.4CI passing

Since Jun 15Pushed 1mo ago2 watchersCompare

[ Source](https://github.com/chillerlan/php-authenticator)[ Packagist](https://packagist.org/packages/chillerlan/php-authenticator)[ Docs](https://github.com/chillerlan/php-authenticator)[ Fund](https://ko-fi.com/codemasher)[ RSS](/packages/chillerlan-php-authenticator/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (18)Versions (25)Used By (2)

chillerlan/php-authenticator
============================

[](#chillerlanphp-authenticator)

A generator for counter based ([RFC 4226](https://tools.ietf.org/html/rfc4226)) and time based ([RFC 6238](https://tools.ietf.org/html/rfc6238)) one time passwords (OTP). (a.k.a. Yet Another Google Authenticator Implementation!)

[![PHP Version Support](https://camo.githubusercontent.com/b4578f4316cded10d4f7007886b1965cb9d0ddcd5385aa5ab64650987bcede2f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6368696c6c65726c616e2f7068702d61757468656e74696361746f723f6c6f676f3d70687026636f6c6f723d383839324246266c6f676f436f6c6f723d666666)](https://www.php.net/supported-versions.php)[![version](https://camo.githubusercontent.com/14d9cbec30c2bb9d541d9b2e6989e64d81767e59f14fa41672d540b8ef0809de/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6368696c6c65726c616e2f7068702d61757468656e74696361746f722e7376673f6c6f676f3d7061636b6167697374266c6f676f436f6c6f723d666666)](https://packagist.org/packages/chillerlan/php-authenticator)[![License](https://camo.githubusercontent.com/a8147b8298edccdb61b718f3ec920c7221e50493065037ad08a5ae2bbef08e16/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6368696c6c65726c616e2f7068702d61757468656e74696361746f722e737667)](https://github.com/chillerlan/php-authenticator/blob/main/LICENSE)[![GitHub actions workflow](https://camo.githubusercontent.com/d13313f6b54501f5c8fdebd385bd68c7ebad925b01280d90d1440ee96dd8ae60/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6368696c6c65726c616e2f7068702d61757468656e74696361746f722f63692e796d6c3f6272616e63683d6d61696e266c6f676f3d676974687562266c6f676f436f6c6f723d666666)](https://github.com/chillerlan/php-authenticator/actions?query=branch%3Amain)[![Coverage](https://camo.githubusercontent.com/922e96139a74a0ac379d5aa2160445db84a5822b9b4338e9b4bbd74cf4b7bc89/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f67682f6368696c6c65726c616e2f7068702d61757468656e74696361746f722f6d61696e3f6c6f676f3d636f6465636f76266c6f676f436f6c6f723d666666)](https://app.codecov.io/github/chillerlan/php-authenticator/tree/main)[![Codacy](https://camo.githubusercontent.com/967ba16020f72d4a91ce95f88b308d7e3897491bef14ff8892340d1095e8c794/68747470733a2f2f696d672e736869656c64732e696f2f636f646163792f67726164652f61323739333232356234343834393563393635396632376637663532333830612f6d61696e3f6c6f676f3d636f64616379266c6f676f436f6c6f723d666666)](https://www.codacy.com/gh/chillerlan/php-authenticator/dashboard?branch=main)[![Downloads](https://camo.githubusercontent.com/50fa4f58b50b3204475ee9aeb8695e82488b0d2fd043c87aae05aee2d2732827/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6368696c6c65726c616e2f7068702d61757468656e74696361746f722e7376673f6c6f676f3d7061636b6167697374266c6f676f436f6c6f723d666666)](https://packagist.org/packages/chillerlan/php-authenticator/stats)

Documentation
=============

[](#documentation)

Requirements
------------

[](#requirements)

- PHP 8.4+
    - [`ext-curl`](https://www.php.net/manual/book.curl) for Steam Guard server time synchronization
    - [`ext-sodium`](https://www.php.net/manual/book.sodium) for constant time implementations of base64 encode/decode and hex2bin/bin2hex ([`paragonie/constant_time_encoding`](https://github.com/paragonie/constant_time_encoding) is used as fallback)

Installation
------------

[](#installation)

**requires [composer](https://getcomposer.org)**

via terminal: `composer require chillerlan/php-authenticator`

**composer.json**

```
{
	"require": {
		"php": "^8.4",
		"chillerlan/php-authenticator": "dev-main"
	}
}
```

Note: replace `dev-main` with a [version constraint](https://getcomposer.org/doc/articles/versions.md#writing-version-constraints), e.g. `^5.0` - see [releases](https://github.com/chillerlan/php-authenticator/releases) for valid versions

Profit!

Usage
-----

[](#usage)

### Create a secret

[](#create-a-secret)

The secret is usually being created once during the activation process in a user control panel. So all you need to do there is to display it to the user in a convenient way - as a text string and QR code for example - and save it somewhere with the user data.

```
use chillerlan\Authenticator\{Authenticator, AuthenticatorOptions};

$options = new AuthenticatorOptions;
$options->secret_length = 32;

$authenticator = new Authenticator($options);
// create a secret (stored somewhere in a *safe* place on the server. safe... hahaha jk)
$secret = $authenticator->createSecret();
// you can also specify the length of the secret key, which overrides the options setting
$secret = $authenticator->createSecret(20);
// set an existing secret
$authenticator->setSecret($secret);
```

A secret created with `Authenticator::createSecret()` will also be stored internally, so that you don't need to provide the secret you just created on follow-up operations with the current instance.

### Verify a one time code

[](#verify-a-one-time-code)

Now during the login process - after the user has successfully entered their credentials - you would ask them for a one time code to check it against the secret from your user database.

```
// verify the code
if($authenticator->verify($otp)){
	// that's it - 2FA has never been easier! :D
}
```

#### time based (TOTP)

[](#time-based-totp)

Verify adjacent codes

```
// try the first adjacent
$authenticator->verify($otp, time() - $options->period); // -> true
// try the second adjacent, default is 1
$authenticator->verify($otp, time() + 2 * $options->period); // -> false
// allow 2 adjacent codes
$options->adjacent = 2;
$authenticator->verify($otp, time() + 2 * $options->period); // -> true
```

#### counter based (HOTP)

[](#counter-based-hotp)

```
// switch mode to HOTP
$options->mode = AuthenticatorInterface::HOTP;
// user sends the OTP for code #42, which is equivalent to
$otp = $authenticator->code(42); // -> 123456
// verify [123456, 42]
$authenticator->verify($otp, $counterValueFromUserDatabase) // -> true
```

### URI creation

[](#uri-creation)

In order to display a QR code for a mobile authenticator you'll need an `otpauth://` URI, which can be created using the following method.

- `$label` should be something that identifies the account to which the secret belongs
- `$issuer` is the name of your website or company for example, so that the user is able to identify multiple accounts.

```
$uri = $authenticator->getUri($label, $issuer);

// -> otpauth://totp/my%20label?secret=NKSOQG7UKKID4IXW&issuer=chillerlan.net&digits=6&period=30&algorithm=SHA1
```

#### Notes

[](#notes)

Keep in mind that several URI settings are not (yet) recognized by all authenticators. Check [the Google Authenticator wiki](https://github.com/google/google-authenticator/wiki/Key-Uri-Format#parameters) for more info.

```
// code length, currently 6 or 8
$options->digits = 8;
// valid period between 15 and 60 seconds
$options->period = 45;
// set the HMAC hash algorithm
$options->algorithm = AuthenticatorInterface::ALGO_SHA512;
```

API
---

[](#api)

### `Authenticator`

[](#authenticator)

methodreturndescription`__construct(SettingsContainerInterface $options = null, string $secret = null)`-`setOptions(SettingsContainerInterface $options)``Authenticator`called internally by `__construct()``setSecret(string $secret)``Authenticator`called internally by `__construct()``getSecret()``string``createSecret(int $length = null)``string``$length` overrides `AuthenticatorOptions` setting`code(int $data = null)``string``$data` may be a UNIX timestamp (TOTP) or a counter value (HOTP)`verify(string $otp, int $data = null)``bool`for `$data` see `Authenticator::code()``getUri(string $label, string $issuer, int $hotpCounter = null, bool $omitSettings = null)``string`### `AuthenticatorOptions`

[](#authenticatoroptions)

#### Properties

[](#properties)

propertytypedefaultalloweddescription`$digits``int`66 or 8auth code length`$period``int`3015 - 60validation period (seconds)`$secret_length``int`20&gt;= 16length of the secret phrase (bytes, unencoded binary)`$algorithm``string``SHA1``SHA1`, `SHA256` or `SHA512`HMAC hash algorithm, see `AuthenticatorInterface::HASH_ALGOS``$mode``string``totp``totp`, `hotp`, `battlenet` or `steam`authenticator mode: time- or counter based, see `AuthenticatorInterface::MODES``$adjacent``int`1&gt;= 0number of allowed adjacent codes`$time_offset``int`0\*fixed time offset that will be added to the current time value`$useLocalTime``bool`true\*whether to use local time or request server time`$forceTimeRefresh``bool`false\*whether to force refreshing server time on each call### `AuthenticatorInterface`

[](#authenticatorinterface)

#### Methods

[](#methods)

methodreturndescription`setOptions(SettingsContainerInterface $options)``AuthenticatorInterface``setSecret(string $encodedSecret)``AuthenticatorInterface``getSecret()``string``createSecret(int $length = null)``string``getServertime()``int``getCounter(int $data = null)``int`internal`getHMAC(int $counter)``string`internal`getCode(string $hmac)``int`internal`getOTP(int $code)``string`internal`code(int $data = null)``string``verify(string $otp, int $data = null)``bool`#### Constants

[](#constants)

constanttypedescription`TOTP``string``HOTP``string``STEAM_GUARD``string``ALGO_SHA1``string``ALGO_SHA256``string``ALGO_SHA512``string``MODES``array`map of mode -&gt; classname`HASH_ALGOS``array`list of available hash algorithms [ ![2FA ALL THE THINGS!](https://raw.githubusercontent.com/chillerlan/php-authenticator/main/.github/images/2fa-all-the-things.jpg) ](https://twofactorauth.org)

###  Health Score

58

—

FairBetter than 98% of packages

Maintenance88

Actively maintained with recent releases

Popularity44

Moderate usage in the ecosystem

Community13

Small or concentrated contributor base

Maturity71

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 ~45 days

Recently: every ~1 days

Total

23

Last Release

59d ago

Major Versions

4.1.0 → 5.0.02023-07-08

3.2.0 → 5.2.02024-06-17

4.3.0 → 5.2.12024-07-16

4.4.0 → 5.3.02025-11-24

v4.x-dev → v6.x-dev2026-03-20

PHP version history (6 changes)1.2.0PHP ^5.6 || ^7.0

v2.x-devPHP ^7.0

3.1.0PHP ^7.2 || ^8.0

4.1.0PHP ^7.4 || ^8.0

5.0.0PHP ^8.2

v6.x-devPHP ^8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/ada3d048807a11e536645fb87da881170b18f34c0c61fa09e34807c5d79e0b89?d=identicon)[codemasher](/maintainers/codemasher)

---

Top Contributors

[![codemasher](https://avatars.githubusercontent.com/u/592497?v=4)](https://github.com/codemasher "codemasher (58 commits)")

---

Tags

2-factor2faauthenticatorgoogle-authenticatorhotpphpphp-libraryphp7php8rfc4226rfc6238steamguardtotpotphotptotp2fagoogle2fatwo-factorMFAauthenticatortfarfc4226rfc6238

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/chillerlan-php-authenticator/health.svg)

```
[![Health](https://phpackages.com/badges/chillerlan-php-authenticator/health.svg)](https://phpackages.com/packages/chillerlan-php-authenticator)
```

###  Alternatives

[paragonie/multi-factor

Vendor-agnostic two-factor authentication library

142195.5k2](/packages/paragonie-multi-factor)[christian-riesen/otp

One Time Passwords, hotp and totp according to RFC4226 and RFC6238

885.1M6](/packages/christian-riesen-otp)[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)[infocyph/otp

Simple &amp; Secure Generic OTP, OCRA (RFC6287), TOTP (RFC6238) &amp; HOTP (RFC4226) solution!

136.4k](/packages/infocyph-otp)

PHPackages © 2026

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