Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Authenticator Laravel Package

chillerlan/php-authenticator

PHP 8.4+ library to generate and validate HOTP (RFC 4226) and TOTP (RFC 6238) one-time passwords—Google Authenticator compatible. Includes Steam Guard server time sync (cURL) and constant-time encoding/hex helpers (Sodium or fallback).

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require chillerlan/php-authenticator
    

    Ensure your composer.json specifies PHP 8.4+ and includes ext-curl and ext-sodium (or paragonie/constant_time_encoding as fallback).

  2. First Use Case (TOTP Setup):

    use chillerlan\Authenticator\Authenticator;
    
    $auth = new Authenticator();
    $secret = $auth->createSecret(); // Generate a 20-byte secret (default)
    $user->otp_secret = $secret; // Store in DB
    $qrUri = $auth->getUri('User Account', 'YourAppName'); // Generate QR URI
    
  3. First Use Case (Verification):

    $userSecret = $user->otp_secret;
    $auth->setSecret($userSecret);
    $otp = '123456'; // From user input
    if ($auth->verify($otp)) {
        // Authenticated
    }
    

Where to Look First

  • Authenticator class: Core functionality for secret generation, code verification, and URI creation.
  • AuthenticatorOptions: Configure TOTP/HOTP settings (digits, period, algorithm, etc.).
  • AuthenticatorInterface: Constants for modes (TOTP, HOTP) and algorithms (SHA1, SHA256, SHA512).

Implementation Patterns

Workflows

1. User Onboarding (TOTP Setup)

// In a registration/controller method
$auth = new Authenticator([
    'digits' => 6,
    'period' => 30,
    'algorithm' => AuthenticatorInterface::ALGO_SHA256,
]);

// Generate and display secret (e.g., QR code + manual entry backup)
$secret = $auth->createSecret();
$user->otp_secret = $secret;
$user->save();

// Return QR URI for scanning
return response()->json(['qr_uri' => $auth->getUri('User Email', 'YourApp')]);

2. Login Flow (TOTP Verification)

// In a login controller
$auth = new Authenticator();
$auth->setSecret($user->otp_secret);
$auth->setOptions(new AuthenticatorOptions(['adjacent' => 1])); // Allow 1 adjacent code

$otp = request()->input('otp');
if ($auth->verify($otp)) {
    // Proceed to session/auth
} else {
    return back()->withErrors(['otp' => 'Invalid code']);
}

3. Counter-Based (HOTP) Workflow

// Setup (e.g., during password reset)
$auth = new Authenticator(['mode' => AuthenticatorInterface::HOTP]);
$secret = $auth->createSecret();
$user->otp_secret = $secret;
$user->otp_counter = 0; // Initialize counter
$user->save();

// Verification (e.g., during login)
$auth->setSecret($user->otp_secret);
$auth->setOptions(['mode' => AuthenticatorInterface::HOTP]);

$otp = request()->input('otp');
$storedCounter = $user->otp_counter;
if ($auth->verify($otp, $storedCounter)) {
    $user->otp_counter++; // Increment counter
    $user->save();
}

4. Dynamic Secret Rotation

// Rotate secret periodically (e.g., every 90 days)
$auth = new Authenticator();
$newSecret = $auth->createSecret();
$user->otp_secret = $newSecret;
$user->save();

// Notify user via email with new QR URI
$newUri = $auth->getUri($user->email, 'YourApp');
Mail::to($user->email)->send(new OTPUpdated($newUri));

Integration Tips

Laravel-Specific Patterns

  1. Service Provider Binding:

    // In AppServiceProvider
    $this->app->singleton(Authenticator::class, function () {
        return new Authenticator(config('auth.otp'));
    });
    

    Configure in config/auth.php:

    'otp' => [
        'digits' => env('OTP_DIGITS', 6),
        'period' => env('OTP_PERIOD', 30),
        'algorithm' => \chillerlan\Authenticator\AuthenticatorInterface::ALGO_SHA256,
        'mode' => \chillerlan\Authenticator\AuthenticatorInterface::TOTP,
    ],
    
  2. Middleware for OTP Protection:

    // app/Http/Middleware/VerifyOTP.php
    public function handle(Request $request, Closure $next) {
        if ($request->user()->requires_otp && !$request->user()->otp_verified) {
            $auth = app(Authenticator::class);
            $auth->setSecret($request->user()->otp_secret);
            if (!$auth->verify($request->input('otp'))) {
                return redirect()->route('otp.verify');
            }
        }
        return $next($request);
    }
    
  3. Artisan Command for Secret Management:

    // app/Console/Commands/GenerateOTPSecret.php
    public function handle() {
        $auth = new Authenticator();
        $secret = $auth->createSecret();
        $this->info("New OTP Secret: " . $secret);
        $this->info("QR URI: " . $auth->getUri('Admin Account', 'YourApp'));
    }
    

Testing Patterns

  1. Unit Test for Verification:

    public function test_otp_verification() {
        $auth = new Authenticator();
        $secret = $auth->createSecret();
        $auth->setSecret($secret);
    
        // Mock current time to test specific code
        $this->mockTime(1234567890);
        $expectedCode = $auth->code(); // Get expected OTP
    
        $this->assertTrue($auth->verify($expectedCode));
    }
    
  2. Feature Test for QR URI:

    public function test_qr_uri_generation() {
        $auth = new Authenticator();
        $secret = $auth->createSecret();
        $uri = $auth->getUri('Test User', 'TestApp');
    
        $this->assertStringStartsWith('otpauth://totp/', $uri);
        $this->assertStringContainsString('secret=' . $secret, $uri);
    }
    

Gotchas and Tips

Pitfalls

  1. Time Synchronization Issues:

    • Problem: TOTP relies on server time. If your server clock is skewed, OTPs may fail.
    • Fix: Use useLocalTime: false and ensure NTP synchronization:
      $auth = new Authenticator(['useLocalTime' => false]);
      
    • Steam Guard Workaround: For Steam-like sync, enable forceTimeRefresh:
      $auth = new Authenticator([
          'mode' => AuthenticatorInterface::STEAM_GUARD,
          'forceTimeRefresh' => true,
      ]);
      
  2. Secret Storage:

    • Problem: Secrets must be stored securely (e.g., encrypted in DB). Never log or expose them.
    • Tip: Use Laravel's encrypt():
      $user->otp_secret = encrypt($secret);
      
  3. Adjacent Codes:

    • Problem: Allowing too many adjacent codes (adjacent > 1) can weaken security.
    • Tip: Default to adjacent: 1 and document the risk:
      $auth->setOptions(['adjacent' => 1]);
      
  4. HOTP Counter Management:

    • Problem: Counters must be stored and incremented after successful verification to avoid replay attacks.
    • Fix: Use a transaction:
      DB::transaction(function () use ($user, $auth, $otp) {
          if ($auth->verify($otp, $user->otp_counter)) {
              $user->otp_counter++;
              $user->save();
          }
      });
      
  5. Algorithm Compatibility:

    • Problem: Not all authenticator apps support SHA512 or custom periods.
    • Tip: Stick to SHA1/SHA256 and standard periods (30s):
      $auth = new Authenticator([
          'algorithm' => AuthenticatorInterface::ALGO_SHA256,
          'period' => 30,
      ]);
      
  6. URI Generation Quirks:

    • Problem: Some apps ignore issuer or digits in URIs.
    • Tip: Test with Google Authenticator and Authy. Omit optional settings:
      $auth = new Authenticator(['omitUriSettings
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope