ejarnutowski/laravel-api-key
ejarnutowski/laravel-api-key adds lightweight API key authentication to Laravel applications. Create keys, attach them to users or any model, and guard routes with middleware—a simple alternative to Passport or Sanctum for token-based API access.
Architecture fit. laravel-api-key is a single-responsibility package: a HasApiKeys model trait, a migration/table for issued keys, and a middleware guard that validates an X-Api-Key header (or query parameter) against stored keys. It sits cleanly in Laravel's HTTP kernel as route middleware, so it does not fight the framework — but it is also not an authentication guard. It validates a credential and lets the request through; it does not populate Auth::user(), integrate with Gates/Policies, or register a guard driver. Any authorization semantics (who the caller is, what they may do) must be built on top. For a TPM this is the central architectural constraint: it is a credential verifier, not an identity system.
Integration feasibility. Low friction. Composer install, service-provider auto-discovery, vendor:publish for config and migration, use HasApiKeys on the owning model, attach auth.apikey to the relevant route group. An engineer can wire a working proof of concept in well under a day. The package is small enough that the full source can be read and understood in an afternoon, which materially de-risks integration.
Technical risk. Three risks dominate. First, maintenance posture: 157 stars and a small single-maintainer footprint means the package is a candidate for abandonment; Laravel-version compatibility (service provider APIs, PHP type constraints) will eventually break and there is no vendor SLA. Second, security posture at rest: the critical question is whether keys are stored hashed or in plaintext — plaintext key storage in the database is a disqualifier for anything touching regulated or customer data, and determines whether a fork is required. Third, missing enterprise primitives: no scopes/permissions, no rotation grace periods, no per-key rate limiting, no audit logging, and no constant-time comparison guarantees.
Key questions. Which Laravel/PHP versions are actually supported versus merely untested? Are keys hashed at rest, and is comparison timing-safe? Does the middleware fail closed on malformed or absent keys? Is there a supported path to multiple active keys per principal (zero-downtime rotation)? What is the release cadence and issue-response history over the last 24 months? Can we use it without a hard dependency on its schema?
Stack fit. Appropriate for internal service-to-service calls, webhook verification, partner/tenant integrations, and early-stage product APIs where a bearer-style key is the contracted auth model. It is not the right tool for first-party user authentication, mobile sessions, OAuth flows, or anything requiring delegated scopes — Laravel Sanctum or Passport own that ground. The realistic framing is: a thin, cheap solution for a narrow problem, competing directly with a first-party package that is maintained by the Laravel team.
Migration path. Greenfield adoption is trivial. Brownfield adoption is only worth it if the team is currently hand-rolling key checks in controllers — in which case the package is a modest consolidation win, not a transformation. Critically, do not let call sites depend on the package's trait directly; wrap issuance, validation, and revocation behind an internal ApiKeyService interface so the vendor package is replaceable without touching domain code.
Compatibility. Verify composer constraints against the target Laravel major before committing. If the app is on a newer Laravel than the package's declared support, the options are: (a) pin the app, which is unacceptable, (b) fork and patch, which converts a dependency into owned code, or (c) skip it entirely. Publish and own the migration and config rather than relying on package defaults — this reduces coupling and makes a later swap to Sanctum a data-migration exercise rather than a rewrite.
Sequencing. (1) One-day technical spike: read the source, confirm hashing and comparison behavior, run it against the target Laravel version. (2) Security review gate — if keys are stored in plaintext or comparison is non-constant-time, stop and fork. (3) Wrap behind the internal service interface. (4) Add the operational scaffolding the package lacks: rate limiting, structured auth-failure logging, key age/rotation reporting. (5) Only then expose it to external or partner traffic. If the spike shows meaningful friction, pivot to Sanctum — the abstraction layer makes that a bounded decision rather than a sunk cost.
Maintenance. Assume we maintain it. With a small contributor base, plan for periodic compatibility patches on Laravel upgrades and a fork-and-vendor contingency. Budget a few engineer-days per year, more across major framework upgrades. The upside is that the surface area is tiny, so the maintenance burden is proportionate and auditable.
Support. Community-only: GitHub issues, no commercial backing, no security advisory process beyond the maintainer's attention. For a security-adjacent component, that is a real gap — key-handling code deserves a documented disclosure channel. Mitigate by pinning versions, watching the repo, and keeping the wrapper thin enough that a CVE response is a config change rather than an incident.
Scaling. A database lookup per authenticated request is the cost model. That is fine at low-to-moderate volume and becomes the first bottleneck under load. Mitigate with a short-TTL cache keyed on a hash of the presented token, and ensure revocation invalidates the cache — the classic failure here is a revoked key that keeps working until TTL expiry. Throughput characteristics are otherwise unremarkable; there is no per-request external dependency.
Failure modes. Watch for: expired-but-cached keys remaining valid; revoked keys lingering in cache; absent key treated as valid (fail-open) rather than rejected; keys appearing in access logs via the query-parameter fallback — consider disabling query-string auth entirely in production; compromised keys with no rotation runbook; and silent validation failures with no audit trail. Each needs an explicit operational control, because the package provides none of them.
Ramp-up. Very low. A mid-level engineer understands the entire mechanism — trait, table, middleware — in an hour, and the wrapper interface makes it usable without reading the vendor source at all. Onboarding cost is not the concern; the concerns are longevity, security hardening, and the absence of the primitives (scopes, rotation, audit) that a production API program will ask for within a year.
How can I help you explore Laravel packages today?