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

Drupal7 Password Hasher Laravel Package

selfsimilar/drupal7_password_hasher

PHP package for verifying and generating Drupal 7-compatible password hashes. Useful for migrating users to Laravel or other apps while preserving existing credentials, with support for Drupal’s phpass-based hashing format and validation against stored hashes.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require selfsimilar/drupal7_password_hasher
    

    Add to composer.json if not auto-loaded:

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "SelfSimilar\\Drupal7PasswordHasher\\": "vendor/selfsimilar/drupal7_password_hasher/src/"
        }
    }
    

    Run composer dump-autoload.

  2. First Use Case Verify a Drupal 7 hashed password against a plaintext input:

    use SelfSimilar\Drupal7PasswordHasher\Drupal7PasswordHasher;
    
    $hasher = new Drupal7PasswordHasher();
    $isValid = $hasher->checkPassword('user_input_password', '$S$...drupal7_hash...');
    
  3. Hashing a New Password

    $hash = $hasher->hashPassword('plaintext_password');
    

Where to Look First

  • Source Code: Focus on Drupal7PasswordHasher.php for core logic.
  • Tests: Check tests/ for edge cases (e.g., empty strings, malformed hashes).
  • Drupal 7 Docs: Reference Drupal 7’s password hashing for context.

Implementation Patterns

Workflow: Migrating Drupal 7 Users

  1. Fetch Drupal 7 Data Export user data (e.g., uid, pass) from Drupal 7 via users table or hook_user().
  2. Validate & Hash
    foreach ($drupalUsers as $user) {
        $hasher = new Drupal7PasswordHasher();
        $isValid = $hasher->checkPassword($user['pass'], $user['hash']); // Legacy check
        $newHash = $hasher->hashPassword($user['pass']); // Re-hash for new system
    }
    
  3. Store in Laravel Save to users table with password column:
    User::create([
        'name' => $user['name'],
        'password' => $newHash,
        // Other fields...
    ]);
    

Integration Tips

  • Laravel Auth: Use with Hasher interface (Laravel 8+) via a facade or service binding:
    // app/Providers/AppServiceProvider.php
    public function register()
    {
        $this->app->bind(\Illuminate\Contracts\Hashing\Hasher::class, function ($app) {
            return new Drupal7PasswordHasher();
        });
    }
    
  • Batch Processing: For large migrations, use Laravel queues:
    Queue::push(new HashDrupal7Users($drupalUsersChunk));
    
  • Fallback Hashing: Combine with Laravel’s default hasher for mixed environments:
    $hash = app(\Illuminate\Contracts\Hashing\Hasher::class)->make($password);
    

Common Use Cases

Scenario Implementation
Legacy Login Support Override AuthenticatesUsers trait to use Drupal7PasswordHasher::checkPassword().
Password Reset Tokens Hash tokens with hashPassword() for consistency.
Audit Logs Store original Drupal 7 hashes in password_history for compliance.

Gotchas and Tips

Pitfalls

  1. Hash Format Sensitivity

    • Drupal 7 uses $S$ prefix for hashes. Reject malformed hashes early:
      if (!preg_match('/^\$S\$[1-9]\$[a-zA-Z0-9\.\/]{53}$/', $hash)) {
          throw new \InvalidArgumentException('Invalid Drupal 7 hash format.');
      }
      
    • Laravel’s Hash::check() won’t work—always use this package for Drupal 7 hashes.
  2. Performance

    • Drupal 7’s hashing is CPU-intensive. For bulk operations, pre-generate hashes offline or use a queue.
  3. Salt Handling

    • The package automatically generates salts. Avoid manual salt management to prevent compatibility issues.
  4. Deprecation Risk

    • Drupal 7 is end-of-life. Document migration paths to Laravel’s default hashing (e.g., bcrypt) post-migration.

Debugging

  • Verify Hashes Use Drupal 7’s user_hash_password() for comparison:
    // PHP CLI test:
    require 'vendor/autoload.php';
    $hasher = new \SelfSimilar\Drupal7PasswordHasher\Drupal7PasswordHasher();
    var_dump($hasher->checkPassword('test', '$S$...'));
    
  • Log Hashes Sanitize logs to avoid exposing passwords:
    \Log::debug('Hash length:', strlen($hash)); // Avoid logging full hashes.
    

Extension Points

  1. Custom Hash Verification Extend the class to add pre-check logic (e.g., rate limiting):

    class CustomDrupal7Hasher extends Drupal7PasswordHasher {
        public function checkPassword($plain, $hashed) {
            if ($this->isBruteForceAttempt($plain)) {
                throw new \RuntimeException('Too many attempts.');
            }
            return parent::checkPassword($plain, $hashed);
        }
    }
    
  2. Hybrid Hashing Support both Drupal 7 and Laravel hashes in a single system:

    class HybridHasher {
        public function check($plain, $hashed) {
            if (str_starts_with($hashed, '$2y$')) { // Laravel bcrypt
                return \Hash::check($plain, $hashed);
            }
            return (new Drupal7PasswordHasher())->checkPassword($plain, $hashed);
        }
    }
    
  3. Configuration Override salt length or iterations (not recommended unless necessary):

    $hasher = new Drupal7PasswordHasher(8, 1); // 8-char salt, 1 iteration (default: 53, 1)
    

Laravel-Specific Quirks

  • Hashing Service Binding If using Laravel’s Hash facade, bind the package’s hasher to avoid conflicts:
    // config/auth.php
    'defaults' => [
        'password' => \SelfSimilar\Drupal7PasswordHasher\Drupal7PasswordHasher::class,
    ],
    
  • Testing Mock the hasher in PHPUnit:
    $mockHasher = $this->createMock(Drupal7PasswordHasher::class);
    $mockHasher->method('checkPassword')->willReturn(true);
    $this->app->instance(Drupal7PasswordHasher::class, $mockHasher);
    
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor