A PHP library for generating and validating one time passwords (TOTP only) according to RFC 6238.
RSCT_OTP is compatible with Google Authenticator available for Android and iPhone and any other TOTP based implementations.
- PHP 7.2 or higher
Install the contents of lib directory somewhere in your project.
<?php
require_once("rsct_otp/lib/rsct_otp.php");
$totp = new \RSCT_OTP\TOTP("base32secret3232");
$totp = new \RSCT_OTP\TOTP("base32secret3232", array("issuer" => "My Service"));
$totp->now(); # => "492039"
# OTP verified for current time - returns timestamp of the current interval
# period.
$totp->verify("492039"); # => 1474590700
# OTP fails to verify - returns nil
$totp->verify("492039"); # => nil
By keeping track of the last time a user's OTP was verified, we can prevent token reuse during the interval window (default 30 seconds)
The following is an example of this in action:
$user = User::find(someUserID);
$totp = new \RSCT_OTP\TOTP(user.otp_secret);
$totp->now(); # => "492039"
# Let's take a look at the last time the user authenticated with an OTP
$user->last_otp_at; # => 1432703530
# Verify the OTP
$last_otp_at = $totp->verify("492039", array("after" => $user->last_otp_at)); #=> 1472145760
# RSCT_OTP returns the timestamp(int) of the current period
# Store this on the user's account
$user->update(array("last_otp_at" => $last_otp_at));
# Someone attempts to reuse the OTP inside the 30s window
$last_otp_at = $totp->verify("492039", array("after" => $user->last_otp_at)); #=> nil
# It fails to verify because we are still in the same 30s interval window
Some users may enter a code just after it has expired. By adding 'drift' you can allow for a recently expired token to remain valid.
$totp = new \RSCT_OTP\TOTP("base32secret3232");
$now = 1474590600; #2016-09-23 00:30:00 UTC
$totp->at($now); # => "250939"
# OTP verified for current time along with 15 seconds earlier
# ie. User enters a code just after it expired
$totp->verify("250939", array("drift_behind" => 15, "at" => now + 35)); # => 1474590600
# User waits too long. Fails to validate previous OTP
$totp->verify("250939", array("drift_behind" => 15, "at" => now + 45)); # => nil
RSCT_OTP::Base32.random # returns a 160 bit (32 character) base32 secret. Compatible with Google Authenticator
Note: The Base32 format conforms to RFC 4648 Base32
Provisioning URI's generated by RSCT_OTP are compatible with most One Time Password applications, including Google Authenticator.
$totp = new RSCT_OTP\TOTP("base32secret3232", array("issuer" => "My Service"));
$totp->provisioning_uri("alice@google.com"); # => 'otpauth://totp/My%20Service:alice@google.com?secret=base32secret3232&issuer=My%20Service'
This can then be rendered as a QR Code which the user can scan using their mobile phone and the appropriate application.
Install composer (https://getcomposer.org/download/) and phpunit (https://phpunit.de/getting-started/phpunit-9.html).
vendor/bin/phpunit tests
This software is released under MIT licence. See LICENSE file.