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

Hawk Laravel Package

dflydev/hawk

PHP implementation of the Hawk HTTP authentication scheme. Build a client via ClientBuilder, sign requests with MAC-based Authorization headers using credentials, URL and method, with optional payload/content-type, nonce and ext (plus Oz app/dlg support).

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Installation:

    composer require dflydev/hawk
    
  2. First Use Case: Secure an API endpoint with Hawk authentication. Start by creating a client for signing requests and a server for validating them.

    // app/Providers/AppServiceProvider.php
    use Dflydev\Hawk\Client\ClientBuilder;
    use Dflydev\Hawk\Server\ServerBuilder;
    
    public function register()
    {
        $this->app->singleton('hawk.client', function () {
            return ClientBuilder::create()->build();
        });
    
        $this->app->singleton('hawk.server', function () {
            return ServerBuilder::create(function ($id) {
                // Fetch credentials from your database or config
                return new \Dflydev\Hawk\Credentials\Credentials(
                    config('hawk.shared_key'),
                    'sha256',
                    $id
                );
            })->build();
        });
    }
    
  3. Configure Hawk in config/hawk.php:

    return [
        'shared_key' => env('HAWK_SHARED_KEY'),
        'timestamp_skew_sec' => 60,
        'localtime_offset_sec' => 0,
    ];
    

Implementation Patterns

Client-Side Workflow

  1. Signing Requests: Use the client to sign outgoing requests in middleware or services.

    // app/Http/Middleware/SignRequest.php
    public function handle($request, Closure $next)
    {
        $credentials = new \Dflydev\Hawk\Credentials\Credentials(
            config('hawk.shared_key'),
            'sha256',
            auth()->id()
        );
    
        $client = app('hawk.client');
        $requestObj = $client->createRequest(
            $credentials,
            $request->fullUrl(),
            $request->method(),
            [
                'payload' => $request->getContent(),
                'content_type' => $request->header('Content-Type'),
            ]
        );
    
        $request->headers->set(
            $requestObj->header()->fieldName(),
            $requestObj->header()->fieldValue()
        );
    
        return $next($request);
    }
    
  2. Authenticating Responses: Verify server responses in middleware or controllers.

    // app/Http/Middleware/VerifyResponse.php
    public function handle($request, Closure $next)
    {
        $response = $next($request);
    
        if ($response->headers->has('Server-Authorization')) {
            $credentials = new \Dflydev\Hawk\Credentials\Credentials(
                config('hawk.shared_key'),
                'sha256',
                auth()->id()
            );
    
            $client = app('hawk.client');
            $isAuthenticated = $client->authenticate(
                $credentials,
                $requestObj, // Store this from the request phase
                $response->headers->get('Server-Authorization'),
                [
                    'payload' => $response->getContent(),
                    'content_type' => $response->header('Content-Type'),
                ]
            );
    
            if (!$isAuthenticated) {
                abort(403, 'Unauthorized response');
            }
        }
    
        return $response;
    }
    

Server-Side Workflow

  1. Validating Requests: Use the server to validate incoming requests in middleware or controllers.

    // app/Http/Middleware/ValidateHawk.php
    public function handle($request, Closure $next)
    {
        $server = app('hawk.server');
    
        try {
            $response = $server->authenticate(
                $request->method(),
                parse_url($request->fullUrl(), PHP_URL_HOST),
                parse_url($request->fullUrl(), PHP_URL_PORT) ?: 80,
                parse_url($request->fullUrl(), PHP_URL_PATH) . '?' . $request->query->__toString(),
                $request->header('Content-Type'),
                $request->getContent(),
                $request->header('Authorization')
            );
    
            // Attach credentials to the request for later use
            $request->setHawkCredentials($response->credentials());
            $request->setHawkArtifacts($response->artifacts());
    
        } catch (\Dflydev\Hawk\Server\UnauthorizedException $e) {
            abort(401, 'Unauthorized');
        }
    
        return $next($request);
    }
    
  2. Signing Responses: Sign server responses in controllers or middleware.

    // app/Http/Controllers/ApiController.php
    public function show(Request $request)
    {
        $server = app('hawk.server');
        $credentials = $request->hawkCredentials;
        $artifacts = $request->hawkArtifacts;
    
        $header = $server->createHeader($credentials, $artifacts, [
            'payload' => $this->getResponsePayload(),
            'content_type' => 'application/json',
        ]);
    
        return response()->json($this->getResponsePayload())
            ->header($header->fieldName(), $header->fieldValue());
    }
    

Integration with Laravel

  1. Leverage Laravel's Service Container: Bind Hawk client/server instances to the container for easy access.

  2. Use Middleware for Centralized Logic: Place Hawk logic in middleware to avoid repetition across controllers.

  3. Store Credentials Securely: Use Laravel's env() or config() to manage shared keys securely.

  4. Extend Request/Response Objects: Add Hawk-specific methods to Laravel's Request and Response classes for seamless integration.

    // app/Http/Requests/HawkRequest.php
    trait HawkRequest
    {
        public function hawkCredentials()
        {
            return $this->attributes->get('hawk.credentials');
        }
    
        public function setHawkCredentials($credentials)
        {
            $this->attributes->set('hawk.credentials', $credentials);
        }
    
        // Similar methods for artifacts
    }
    

Gotchas and Tips

Common Pitfalls

  1. Nonce Management:

    • Ensure your nonce provider generates unique, non-reusable nonces.
    • Store used nonces in a database or cache to prevent replay attacks.
    • Example: Use Laravel's Cache facade to store nonces.
    // app/Providers/AppServiceProvider.php
    $this->app->singleton('hawk.nonce_provider', function () {
        return new class {
            public function generate()
            {
                return Str::random(32);
            }
    
            public function validate($nonce)
            {
                return Cache::has("hawk.nonce.$nonce") ? false : Cache::put("hawk.nonce.$nonce", true, now()->addMinutes(5));
            }
        };
    });
    
  2. Timestamp Skew:

    • Configure timestamp_skew_sec to allow for minor clock differences between client and server.
    • Default is 60 seconds; adjust based on your infrastructure.
  3. Payload Hashing:

    • Ensure the content_type is correctly set when calculating payload hashes.
    • For binary data (e.g., file uploads), use application/octet-stream.
  4. Bewit Usage:

    • Bewits are only for GET and HEAD requests.
    • Bewits expire after the specified TTL; handle expiration gracefully.
  5. Error Handling:

    • Catch UnauthorizedException on the server side to return appropriate HTTP status codes (e.g., 401).
    • Log failed authentication attempts for security auditing.

Debugging Tips

  1. Log Hawk Headers: Log the Authorization and Server-Authorization headers for debugging.

    \Log::debug('Hawk Authorization', [
        'header' => $request->header('Authorization'),
        'server_header' => $response->headers->get('Server-Authorization'),
    ]);
    
  2. Validate Credentials: Double-check that credentials (shared key, algorithm, ID) match between client and server.

  3. Time Synchronization: Ensure client and server clocks are synchronized. Use NTP or a time synchronization service if needed.

  4. Payload Mismatches: Verify that the payload and content_type used in signing match those sent/received.

    • For POST requests, ensure the raw body is used, not Laravel's parsed input.

Extension Points

  1. Custom Crypto: Extend Dflydev\Hawk\Crypto\Crypto to support additional algorithms or modify MAC calculation logic.

  2. Nonce Providers: Implement custom nonce providers for specific use cases (e.g., UUID-based nonces).

  3. Credentials Providers: Use Laravel's Auth system to dynamically fetch credentials.

    $credentialsProvider = function ($id) {
        $user = User::find($id);
        return new \Dflydev\Hawk\Credentials\Credentials(
            $user->hawk_shared_key,
            'sha256',
            $user->id
        );
    };
    
  4. Artifacts Handling: Extend Dflydev\Hawk\Crypto\Artifacts to include custom metadata in Hawk headers.

  5. Middleware Chaining: Combine Hawk middleware with Laravel's built-in middleware (e.g.,

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.
babenkoivan/elastic-client
innmind/static-analysis
innmind/coding-standard
datacore/hub-sdk
alengo/sulu-http-cache-bundle
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
imbo/imbo-coding-standard
visualbuilder/filament-lottie
servicioslineaonce/starter-kit
atomcoder/laravel-reorderable
irajul/filament-shadcn-theme
agtp/agtp-php
agtp/mod-php
centraldesktop/protobuf-php