sonata-project/google-authenticator
Installation
composer require sonata-project/google-authenticator
Add to composer.json if using Laravel’s autoloader:
"autoload": {
"psr-4": {
"App\\": "app/",
"Sonata\\GoogleAuthenticator\\": "vendor/sonata-project/google-authenticator/src/"
}
}
Run composer dump-autoload.
First Use Case Generate a secret key and QR code for a user:
use Sonata\GoogleAuthenticator\GoogleAuthenticator;
use Sonata\GoogleAuthenticator\GoogleQrUrl;
$ga = new GoogleAuthenticator();
$secret = $ga->generateSecret(); // e.g., "JBSWY3DPEHPK3PXP"
$qrCodeUrl = GoogleQrUrl::generate('YourAppName', $secret, 'user@example.com');
Display $qrCodeUrl in the Google Authenticator app or render it as a QR code in your view.
User Onboarding
users table):
$user->google_auth_secret = $ga->generateSecret();
$user->save();
Verification Logic
$otp = $request->input('otp');
$isValid = $ga->checkCode($user->google_auth_secret, $otp);
namespace App\Http\Middleware;
use Closure;
use Sonata\GoogleAuthenticator\GoogleAuthenticator;
class VerifyTwoFactor
{
public function handle($request, Closure $next)
{
$ga = new GoogleAuthenticator();
$otp = $request->input('otp');
if (!$ga->checkCode($request->user()->google_auth_secret, $otp)) {
abort(403, 'Invalid OTP');
}
return $next($request);
}
}
Recovery Codes
$recoveryCodes = str_split(strtoupper(bin2hex(random_bytes(16))));
$user->recovery_codes = json_encode($recoveryCodes);
$user->save();
Laravel Service Provider Bind the authenticator to the container for dependency injection:
public function register()
{
$this->app->singleton(GoogleAuthenticator::class, function () {
return new GoogleAuthenticator();
});
}
Inject via constructor:
public function __construct(GoogleAuthenticator $ga) {
$this->ga = $ga;
}
Caching Secrets Cache the last valid OTP to prevent replay attacks (e.g., using Laravel’s cache):
$cacheKey = "user_{$user->id}_otp";
if ($ga->checkCode($user->google_auth_secret, $otp) && !$request->hasSession()) {
Cache::put($cacheKey, $otp, now()->addMinutes(1));
}
Rate Limiting Use Laravel’s throttling middleware to limit OTP attempts:
Route::middleware(['throttle:5,1'])->group(function () {
// OTP verification routes
});
Time Synchronization
Secret Storage
$user->google_auth_secret = encrypt($ga->generateSecret());
Deprecated Methods
generateSecret()checkCode($secret, $code)GoogleQrUrl::generate()OTP Length
Test Locally
Use the Google Authenticator app or emulator to verify secrets before deployment.
Example test secret: JBSWY3DPEHPK3PXP (generates predictable codes for testing).
Logging Log failed attempts to debug synchronization issues:
if (!$ga->checkCode($secret, $otp)) {
Log::warning("OTP failure for user {$user->id}. Secret: {$secret}, Code: {$otp}");
}
Custom Algorithms
GoogleAuthenticator to support TOTP (Time-based OTP) with custom parameters:
$ga = new GoogleAuthenticator();
$ga->getCode($secret); // Default: 30s interval, 6 digits
getCode() method to adjust intervals/digits.Multi-Factor UI
$request->session()->put('2fa_verified', true);
Backup Codes
class CustomAuthenticator extends GoogleAuthenticator
{
public function __construct($timeStep = 30, $window = 1, $digits = 6)
{
parent::__construct($timeStep, $window, $digits);
}
}
How can I help you explore Laravel packages today?