Weave 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 Server Bundle Laravel Package

hashnz/hawk-server-bundle

Symfony bundle that adds server-side Hawk HTTP authentication to your app. Validate Hawk Authorization headers, verify MACs, timestamps, and nonces, and protect routes with configurable credentials.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package — there is no service provider, no config/hawk.php, and no facade. As a Laravel developer, you have two realistic ways in:

  1. Use it as a spec reference. Hawk is a well-defined HTTP auth scheme (HMAC-SHA256 over a canonicalized request string, plus ts/nonce for replay protection). Reading this bundle's validator is often faster than reading the RFC-equivalent spec, and the logic ports to a Laravel middleware in ~100 lines.
  2. Bridge to an actual Symfony service. Only worth it if the Symfony app already exists and you're the one integrating with it.

Minimal steps if you do install it:

composer require hashnz/hawk-server-bundle
// config/bundles.php
Hashnz\HawkServerBundle\HawkServerBundle::class => ['all' => true],

Then look in this order:

  • The bundle's DependencyInjection/Configuration.php — this is the authoritative list of config keys; the README may lag behind it.
  • The security factory / authentication listener — that's where the Hawk header is parsed and the MAC compared.
  • The README's example config/packages/hawk_server.yaml (typical shape: a map of id => shared_key, plus a timestamp-skew window).

First use case: protect a machine-to-machine endpoint — internal service calls, webhooks, a CLI agent — where both sides already share a secret. Hawk is a poor fit for browser clients or third-party integrations, because every client needs a provisioned key and a roughly accurate clock.

Implementation Patterns

Keep Hawk on its own firewall. Don't mix it into your session-based main firewall; register a dedicated one for /api so a failed Hawk header returns a clean 401 instead of redirecting to a login form.

Credential lookup is the main extension point. Static id => key config is fine for one or two clients. Beyond that, implement the bundle's credential-provider interface against your api_clients table (store a hash of the key, not the key). Cache lookups — this runs on every request.

You must supply a nonce store. Hawk's replay protection is only as good as the cache behind it. Redis with SETNX + TTL equal to your skew window (e.g. 60s) is the standard shape; key it as hawk:nonce:{id}:{nonce} so one noisy client can't evict another's entries.

Client side is not in this bundle. It's server-only. Use the hawk npm package, a Guzzle Hawk middleware, or hand-roll it. In Laravel, generating the header looks like:

$ts = time(); $nonce = bin2hex(random_bytes(6));
$normalized = implode("\n", [
    'hawk.1.header', $ts, $nonce, $method, $path.$query, $host, $port, $hash, $ext,
]);
$mac = base64_encode(hash_hmac('sha256', $normalized, $key, true));

Note the hash component is the SHA-256 of the body (empty string if no body) — that's what binds the payload to the header.

Testing: inject a fixed clock and a deterministic nonce generator, then assert on the exact normalized string. Header-validation bugs are almost always canonicalization bugs, and a test that prints the string you signed is worth more than ten integration tests.

Gotchas and Tips

  • Zero dependents and near-zero stars is the headline risk. Treat this as a reference implementation you vendor or pin to an exact version, not a dependency you expect security patches for. Authentication code with no downstream users does not get audited.
  • Clock skew will bite you first. Defaults are usually ±60s; a container with a drifted clock fails intermittently and looks like a key problem. Enforce NTP and log ts deltas on rejection.
  • Proxies break the MAC. The server recomputes the canonical string from the actual request, so host and port must match what the client signed. Behind a load balancer, configure trusted proxies or the MAC will never verify on non-default ports. This is the single most common "it works locally" failure.
  • Normalize paths exactly. Percent-encoding, trailing slashes, and query-string ordering all feed the MAC. Sign and verify from the raw request URI, not a framework-normalized route.
  • Include ext in the MAC if present. Omitting it silently allows tampering with that field.
  • Distinguish 401 from 403. Missing/malformed/expired header → 401 with WWW-Authenticate: Hawk. Valid MAC but unauthorized client → 403. Symfony's security listeners sometimes flatten these.
  • Debug by logging the signed string, never the key. A one-character diff (usually port or a double \n) explains nearly every verification failure.
  • Honest recommendation: if the goal is a Laravel API calling a Laravel API, a small middleware with hash_equals() and a Redis nonce check is lower risk than bridging a Symfony security bundle — you get the same protocol guarantees and control the error responses, the clock source, and the credential store directly.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings