chillerlan / php-authenticator
A generator for counter- and time based 2-factor authentication codes (Google Authenticator). PHP 8.2+
Fund package maintenance!
Ko-Fi
Installs: 58 716
Dependents: 2
Suggesters: 4
Security: 0
Stars: 43
Watchers: 4
Forks: 2
Open Issues: 0
Requires
- php: ^8.2
- chillerlan/php-settings-container: ^3.2.1
- paragonie/constant_time_encoding: ^3.0
Requires (Dev)
- ext-curl: *
- ext-json: *
- ext-sodium: *
- phpmd/phpmd: ^2.15
- phpstan/phpstan: ^1.11
- phpstan/phpstan-deprecation-rules: ^1.2
- phpunit/phpunit: ^11.2
- squizlabs/php_codesniffer: ^3.10
Suggests
- chillerlan/php-qrcode: Create QR Codes for use with an authenticator app.
README
A generator for counter based (RFC 4226) and time based (RFC 6238) one time passwords (OTP). (a.k.a. Yet Another Google Authenticator Implementation!)
Documentation
Requirements
- PHP 8.2+
ext-curl
for Steam Guard server time synchronizationext-sodium
for constant time implementations of base64 encode/decode and hex2bin/bin2hex (paragonie/constant_time_encoding
is used as fallback)
Installation
requires composer
via terminal: composer require chillerlan/php-authenticator
composer.json
{ "require": { "php": "^8.2", "chillerlan/php-authenticator": "dev-main" } }
Note: replace dev-main
with a version constraint, e.g. ^5.0
- see releases for valid versions
Profit!
Usage
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
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)
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)
// 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
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
Keep in mind that several URI settings are not (yet) recognized by all authenticators. Check the Google Authenticator wiki 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;