TOTP two-factor authentication component for PHP 8.1+.
The package provides a small, dependency-light TOTP implementation with Base32 secret handling, otpauth:// URI generation, QR image providers, and a factory-based public API.
- PHP
>=8.1 ext-hashext-json
composer require lemonade/two-factorCreate the component through AppTwoFactorFactory:
<?php declare(strict_types=1);
use Lemonade\Authorization\AppTwoFactorFactory;
$app = AppTwoFactorFactory::createForIssuer('lemonadeframework.cz');
$secret = $app->createSecret();
$uri = $app->getOtpAuthUri('user@example.com', $secret);
$isValid = $app->verifyCode($secret, $code);$secret = $app->createSecret();By default, createSecret() generates a 160-bit secret, encoded as 32 Base32 characters.
$secret = $app->createSecret(200); // ceil(200 / 5) Base32 charactersThe minimum generated secret size is 160 bits. Calling createSecret(80) still returns a 160-bit / 32-character Base32 secret.
Existing shorter Base32 secrets remain usable for verification. For example, previously stored 16-character Base32 secrets are still normalized and accepted by getCode() and verifyCode().
Use the URI when provisioning an authenticator app directly or when rendering a QR code elsewhere:
$uri = $app->getOtpAuthUri('user@example.com', $secret);The URI includes:
secretissueralgorithmdigitsperiod
URI values are encoded with RFC3986 encoding.
$dataUri = $app->getImageUri('user@example.com', $secret);This returns a data:image/...;base64,... URI using the configured QR image provider.
Pass a custom image provider when creating the component:
use Lemonade\Authorization\AppTwoFactorFactory;
use Lemonade\Authorization\Infrastructure\Image\GoogleChartProvider;
$app = AppTwoFactorFactory::create(
imageProvider: new GoogleChartProvider(),
);$isValid = $app->verifyCode($secret, $code);You can also retrieve the matched TOTP timeslice and store it in your application to prevent replay:
$timeslice = 0;
$isValid = $app->verifyCode($secret, $code, discrepancy: 1, time: null, timeslice: $timeslice);The library does not store replay state internally.
use Lemonade\Authorization\AppTwoFactorFactory;
$app = AppTwoFactorFactory::createForIssuer('lemonadeframework.cz');The issuer can be any non-empty string. It does not need to be a domain.
Use AppTwoFactorOptions for explicit configuration:
use Lemonade\Authorization\AppTwoFactorFactory;
use Lemonade\Authorization\Domain\DTO\AppTwoFactorOptions;
use Lemonade\Authorization\Domain\Enum\TotpAlgorithm;
$app = AppTwoFactorFactory::create(new AppTwoFactorOptions(
issuer: 'lemonadeframework.cz',
algorithm: TotpAlgorithm::SHA1,
period: 30,
digits: 6,
));Supported TOTP code lengths are 6 and 8 digits. The default is 6 digits, which is the common authenticator app default. Use 8 digits only when your authenticator app and application flow both support it.
Algorithms are configured with the TotpAlgorithm enum:
use Lemonade\Authorization\Domain\Enum\TotpAlgorithm;
TotpAlgorithm::SHA1;
TotpAlgorithm::SHA256;
TotpAlgorithm::SHA512;SHA1 is the default because it has the broadest compatibility with authenticator applications. SHA256 and SHA512 are supported when the authenticator app supports them.
- SHA1 is the default for authenticator compatibility.
- SHA256 and SHA512 are supported when the authenticator app supports them.
- Supported TOTP code lengths are 6 and 8 digits. The default is 6 digits.
- MD5 is not supported.
- Secret generation uses secure random bytes by default.
- OpenSSL is only used as a fallback when it reports strong randomness.
- SSL verification is not disabled by the downloader.
- Base32 secrets are normalized by uppercasing, removing spaces and hyphens, and tolerating optional padding.
Run the basic example from the package directory:
php examples/basic.phpThe package includes PHPUnit tests, PHPStan analysis at max level with strict rules and bleeding edge enabled, PHP syntax linting, and PHP CS Fixer configuration.
composer lint
composer cs:check
composer stan
composer test
composer check
composer test:ci
composer stan:ci
composer check:ciThe repository contains GitHub Actions workflows for:
- PHP Lint
- PHPUnit
- PHPStan
- PHP CS Fixer
Recommended local full check:
composer checkRecommended CI-style local check:
composer check:ciAppTwoFactoris no longer created directly with the old constructor.- Use
AppTwoFactorFactoryto create configured instances. - Algorithms are configured with the
TotpAlgorithmenum. - Old algorithm constants were removed.
- Legacy providers and interfaces were removed.
- Stored Base32 secrets remain usable.
composer lint
composer cs:check
composer cs:fix
composer stan
composer test
composer check
composer test:ci
composer stan:ci
composer check:ci