Laragear WebAuthn

repository·5.x·Indexed 19 days ago

https://github.com/laragear/webauthn

A Laravel package for authenticating users using Passkeys (WebAuthn), supporting biometric data, fingerprints, and patterns. It provides an Eloquent User Provider driver, a JavaScript helper (@laragear/webpass), and tools for managing attestation and assertion ceremonies. Note: This package is no longer maintained and has been superseded by laravel/passkeys.

Tokens
13.2K
Snippets
51
Records
61
Agent score
63%

What's inside laragear-webauthn

  1. Laravel Octane compatibility

    5.x
    This package is compatible with Laravel Octane. It does not use singletons that rely on stale application, config, or request instances, and it does not use static properties that are written to during a request.
  2. Manually Attest and Assert users

    5.x

    If you need to perform WebAuthn ceremonies manually (e.g., during user registration), you can use the following pipeline classes:

    • AttestationCreator: Creates a request to create a WebAuthn Credential.
    • AttestationValidator: Validates a response with the WebAuthn Credential. Note: This instantiates a storable credential but does not save it automatically, allowing you to modify the model before persistence.
    • AssertionCreator: Creates a request to validate a WebAuthn Credential.
    • AssertionValidator: Validates a response for a WebAuthn Credential.

    Validation methods no longer require the current Request instance; they accept a JSON array of data. You can use the fromRequest() helper or manually use Laragear\WebAuthn\JsonTransport.

  3. Security considerations for WebAuthn implementation

    5.x

    When using this WebAuthn implementation, be aware of the following security behaviors:

    • Challenge Management: Registration (attestation) and Login (assertion) challenges use the request session by default. Challenges are created with random bytes, retrieved and deleted from the source upon resolution, and expire after 60 seconds.
    • Concurrency: Only one ceremony can be performed at a time because ceremonies share the same challenge key.
    • User Identity: The WebAuthn User Handle is a UUID v4 and is reused when creating new credentials for the same user.
    • Credential Control: Credentials can be blacklisted (enabled/disabled).
    • Data Protection: Public Keys are automatically encrypted in the database using the application key.
  4. Add relationships to package models

    5.x

    To implement relationships between the package models and your own models, follow two steps:

    1. Register the relationship in the Model: Use resolveRelationUsing() within the booted() callback in bootstrap/app.php to define how the relationship is resolved.
    2. Add the foreign key column in the Migration: Use the Car::migration() method and pass a callback to add the necessary foreign key column (e.g., using foreignIdFor()).
    // 1. Register relationship in bootstrap/app.php
    Car::resolveRelationUsing('driver', function (Car $car) {
        return $car->belongsTo(Driver::class, 'driver_id');
    });
    
    // 2. Add column in the migration file
    return Car::migration(function (Blueprint $table) {
        $table->foreignIdFor(Driver::class);
    });
  5. Customize package migrations

    5.x
    The package uses a simplified migration approach where the migration file calls Model::migration(). You can extend this migration to add custom columns, handle relationships, or execute logic during the up/down lifecycle.
  6. Customize package Models

    5.x

    You can modify the default behavior of the package's Models (such as changing the table name, database connection, or hiding attributes) using the customize() method. This should ideally be done within the booted() callback in your bootstrap/app.php file. The package migrations will automatically respect any table or connection changes made via customize().

    use Illuminateoundation\
    use Illuminate\Foundation\Configuration\Exceptions;
    use Illuminate\Foundation\Configuration\Middleware;
    use Vendor\Package\Models\Driver;
    
    return Application::configure(basePath: dirname(__DIR__))
        ->booted(function () {
            // Customize the model
            Car::customize(function (Car $model) {
                $model->setTable('my_custom_car');
                $model->setConnection('readonly-mysql');
                
                $model->setHidden('private_notes');
            });
        })->create();
  7. Configure Laragear WebAuthn settings

    5.x

    You can override the default WebAuthn configuration by publishing the config file to config/webauthn.php.

    It is recommended to use environment variables instead of modifying the config file directly. The configuration includes settings for the Relying Party, allowed origins, and challenge parameters.

    php artisan vendor:publish --provider="Laragear\WebAuthn\WebAuthnServiceProvider" --tag="config"
  8. Initialize WebAuthn with artisan commands

    5.x

    Use the following commands to publish configuration, routes, and migration files, then apply the migrations to create the necessary table for WebAuthn Credentials (Passkeys).

    php artisan webauthn:install
    php artisan migrate
  9. Requirements for laragear/webauthn

    5.x

    Ensure your environment meets the following requirements:

    • PHP: 8.3 or later
    • Laravel: 12 or later
    • Extensions:
      • ext-openssl (Required)
      • ext-sodium (Optional, for EdDSA 25519 public keys. If unavailable, you can install paragonie/sodium_compat).
  10. Implement a custom WebAuthnChallengeRepository

    5.x

    By default, challenges are stored in the application Session. To use a different storage mechanism (like Redis or a database) to share challenges across multiple instances, implement the Laragear\WebAuthn\Contracts\WebAuthnChallengeRepository contract.

    Your implementation must include:

    • store(Challenge $challenge, AttestationCreation|AssertionCreation $ceremony): void
    • pull(AttestationValidation|AssertionValidation $ceremony): ?Challenge

    Note that pull() should delete the challenge from the repository once retrieved.

    namespace App\WebAuthn;
    
    use Illuminate\Support\\Facades\\Auth;
    use Illuminate\Support\\Facades\\Cache;
    use Illuminate\Support\\Facades\\Request;
    use Laragear\WebAuthn\\Assertion\\Creator\\AssertionCreation;
    use Laragear\WebAuthn\\Assertion\\Validator\\AssertionValidation;
    use Laragear\WebAuthn\\Attestation\\Creator\\AttestationCreation;
    use Laragear\WebAuthn\\Attestation\\Validator\\AttestationValidation;
    use Laragear\WebAuthn\\Contracts\WebAuthnChallengeRepository;
    use Laragear\WebAuthn\\Challenge\Challenge;
    
    class MyRepository implements WebAuthnChallengeRepository
    {
        /**
         * Puts a ceremony challenge into the repository.
         */
        public function store(Challenge $challenge, AttestationCreation|AssertionCreation $ceremony): void
        {
            Cache::store('redis')->put($this->getFingerprint(), $challenge, $challenge->expiresAt());
        }
    
        /**
         * Pulls a ceremony challenge out from the repository, if it exists.
         */
        public function pull(AttestationValidation|AssertionValidation $ceremony): ?Challenge
        {
            return Cache::store('redis')->pull($this->getFingerprint());
        }
        
        /**
         * Create a fingerprint as a cache key.
         */
        protected function getFingerprint(): string
        {
            $user = Auth::user();
            
            // Use the IP, the user class and its auth identifier to build the cache key.
            return implode('|', [
                'webauthn_challenge', Request::ip(), get_class($user), $user->getAuthIdentifier()
            ]);
        }
    }