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

User Security Laravel Package

laraditz/user-security

Adds user security features for Laravel/Lumen: security PIN, mnemonic key validation/storage, and 2FA support. Includes a UserSecurable trait, SecureUser facade, and configurable hashing key (LUS_KEY) for one-way encryption.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require laraditz/user-security
    

    For Laravel ≥5.5, auto-discovery handles the service provider registration. Otherwise, add Laraditz\UserSecurity\UserSecurityServiceProvider::class to config/app.php.

  2. Publish Config Publish the default configuration:

    php artisan vendor:publish --provider="Laraditz\UserSecurity\UserSecurityServiceProvider" --tag="config"
    

    This generates config/user-security.php with default settings (e.g., pin length, 2FA algorithm).

  3. Run Migrations Publish and run migrations to add security fields to the users table:

    php artisan vendor:publish --provider="Laraditz\UserSecurity\UserSecurityServiceProvider" --tag="migrations"
    php artisan migrate
    

    This adds columns: security_pin, mnemonic_key, two_factor_secret, and two_factor_recovery_codes.

  4. First Use Case: Enabling a Security Pin Assign a pin to a user via Tinker or a controller:

    use Laraditz\UserSecurity\Facades\UserSecurity;
    
    $user = \App\Models\User::find(1);
    UserSecurity::setSecurityPin($user, '1234'); // Default length: 4
    

Implementation Patterns

Core Workflows

1. Security Pin Management

  • Setting/Updating:
    UserSecurity::setSecurityPin($user, $pin);
    UserSecurity::updateSecurityPin($user, $oldPin, $newPin); // For validation
    
  • Validation:
    if (UserSecurity::validateSecurityPin($user, $pin)) {
        // Proceed with secure action
    }
    
  • Integration with Login: Extend Laravel’s AuthenticatesUsers trait to require a pin post-login:
    public function postLogin(Request $request)
    {
        $this->authenticate($request);
        $user = $this->guard()->user();
    
        if (!$request->has('security_pin') || !UserSecurity::validateSecurityPin($user, $request->security_pin)) {
            return back()->withErrors(['pin' => 'Invalid pin.']);
        }
        return redirect()->intended();
    }
    

2. Mnemonic Key Generation/Recovery

  • Generate for a User:
    $mnemonic = UserSecurity::generateMnemonicKey($user);
    // Store $mnemonic securely (e.g., encrypted in DB or session)
    
  • Validate:
    if (UserSecurity::validateMnemonicKey($user, $providedMnemonic)) {
        // Grant access to recovery flow
    }
    
  • Use Case: Passwordless recovery or admin override. Example recovery route:
    Route::post('/recover-account', function (Request $request) {
        $user = User::where('email', $request->email)->first();
        if ($user && UserSecurity::validateMnemonicKey($user, $request->mnemonic)) {
            Auth::login($user);
            return redirect()->route('dashboard');
        }
        return back()->withErrors(['mnemonic' => 'Invalid key.']);
    });
    

3. Two-Factor Authentication (2FA)

  • Enable 2FA:
    $secret = UserSecurity::enableTwoFactorAuth($user);
    // Display QR code or manual entry key (e.g., using `laravel-2fa` or similar)
    
  • Validate 2FA Token:
    if (UserSecurity::validateTwoFactorToken($user, $token)) {
        // Grant access
    }
    
  • Integration with Laravel 2FA Packages: Combine with laravel-2fa for UI/QR generation:
    use Laraditz\UserSecurity\Facades\UserSecurity;
    use LaravelTwoFactorAuth\TwoFactorAuth;
    
    $secret = UserSecurity::enableTwoFactorAuth($user);
    $twoFactor = app(TwoFactorAuth::class);
    $qrCodeUrl = $twoFactor->getQRCodeUrl($user->email, $secret);
    
  • Recovery Codes: Generate/revoke codes via:
    $codes = UserSecurity::generateTwoFactorRecoveryCodes($user, 10); // 10 codes
    UserSecurity::revokeTwoFactorRecoveryCodes($user);
    

4. Bulk Operations

  • Batch Pin Assignment (e.g., for admins):
    $admins = User::where('role', 'admin')->get();
    foreach ($admins as $admin) {
        UserSecurity::setSecurityPin($admin, str_pad(rand(0, 9999), 4, '0', STR_PAD_LEFT));
    }
    

Integration Tips

Middleware for Protected Routes

Create middleware to enforce security checks:

namespace App\Http\Middleware;

use Closure;
use Laraditz\UserSecurity\Facades\UserSecurity;

class RequireSecurityPin
{
    public function handle($request, Closure $next)
    {
        if (!UserSecurity::validateSecurityPin($request->user(), $request->pin)) {
            abort(403, 'Invalid security pin.');
        }
        return $next($request);
    }
}

Register in app/Http/Kernel.php:

protected $routeMiddleware = [
    'pin.required' => \App\Http\Middleware\RequireSecurityPin::class,
];

Usage:

Route::get('/secure-area', function () {
    // ...
})->middleware('auth:web', 'pin.required');

Event Listeners

Extend core events (e.g., registered, password.resetting) to auto-generate security features:

// In EventServiceProvider
protected $listen = [
    'Illuminate\Auth\Events\Registered' => [
        'App\Listeners\GenerateSecurityPinOnRegistration',
    ],
];

Listener:

public function handle($event)
{
    UserSecurity::setSecurityPin($event->user, str_pad(rand(0, 9999), 4, '0'));
}

API Integration

For APIs, return security status in user profiles:

Route::get('/api/user', function (Request $request) {
    return [
        'has_pin' => UserSecurity::hasSecurityPin($request->user()),
        'has_2fa' => UserSecurity::isTwoFactorEnabled($request->user()),
    ];
});

Gotchas and Tips

Pitfalls

  1. Migration Conflicts

    • If the users table already exists, manually add the columns or drop the table before migrating.
    • Columns required:
      security_pin VARCHAR(255) NULL,
      mnemonic_key VARCHAR(255) NULL,
      two_factor_secret VARCHAR(255) NULL,
      two_factor_recovery_codes TEXT NULL
      
  2. Pin Length Validation

    • Default pin length is 4 digits (configurable in config/user-security.php). Ensure your UI enforces this.
    • Customize via config:
      'pin' => [
          'length' => 6, // Now requires 6-digit pins
      ],
      
  3. Mnemonic Key Collisions

    • The package generates random 12-word mnemonics (like BIP-39). Ensure uniqueness if using as primary recovery.
    • Check for collisions:
      if (UserSecurity::mnemonicExists($mnemonic)) {
          // Regenerate
      }
      
  4. 2FA Secret Storage

    • The two_factor_secret is stored in plaintext. Encrypt it if compliance requires:
      use Illuminate\Support\Facades\Crypt;
      
      $encryptedSecret = Crypt::encrypt($secret);
      UserSecurity::setTwoFactorSecret($user, $encryptedSecret);
      
    • Update validation accordingly:
      $secret = Crypt::decrypt(UserSecurity::getTwoFactorSecret($user));
      
  5. Recovery Code Exhaustion

    • Each recovery code is single-use. Track usage to avoid lockouts:
      if (UserSecurity::isRecoveryCodeUsed($user, $code)) {
          return back()->withErrors(['code' => 'Used or invalid.']);
      }
      
  6. Laravel Caching

    • Security checks (e.g., pin validation) may benefit from caching. Cache the has_pin or is_2fa_enabled flags:
      $user->cache([has_pin => UserSecurity::hasSecurityPin($user)]);
      

Debugging Tips

  1. Log Security Events Add logging to UserSecurityServiceProvider:

    public function boot()
    {
        \Log::info('UserSecurity initialized');
        // ...
    }
    

    Or wrap calls in logs:

    \Log::debug('Validating pin for user', ['user_id' => $user->id, 'pin' => $pin]);
    
  2. Test Pin/2FA Locally Use Tinker to test:

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.
ilhamsyabani/laravel-volt-starter
thethunderturner/filament-latex
ghostcompiler/laravel-querybuilder
webrek/laravel-telescope-mongodb
anousss007/blatui
zatona-eg/zatona-eg-api
cocosmos/filament-sticky-save-bar
patrickbussmann/oauth2-apple
3brs/enterprise-security-bundle
anousss007/vigilance
supportpal/eloquent-model
ardenexal/fhir-models
laravel-at/laravel-image-sanitize
romalytar/yammi-audit-log-laravel
ardenexal/fhir-validation
arshaviras/weather-widget
laravel-chronicle/core
sunchayn/nimbus
daikazu/eloquent-salesforce-objects
unseen-codes/chat