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

Api Key Authentication Bundle Laravel Package

ma27/api-key-authentication-bundle

Symfony bundle that adds API key authentication to your app. Validate keys from request headers or query parameters, resolve them to users via a provider, and protect firewall routes for REST APIs and machine-to-machine access with minimal configuration.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Verdict up front — revised, conclusion unchanged. The 2.0.0-alpha1 release changes the package's maintenance story but not its applicability. It remains a Symfony bundle with no Laravel service provider, guard driver, facade, or middleware, and no third-party bridge. What has changed is that the "archived since 2016" framing is now stale: there is an active maintainer and a modernization branch. That is a genuine positive signal for the project, but it is delivered as an explicitly non-production-ready alpha whose own release notes warn that "some parts of the docs might be out-of-date." The recommendation stands: port the design, do not install the package. The 7.16 "opportunity" score still measures the problem space (API-key auth is a recurring need), not this artifact's viability.

Architecture fit. Unchanged and structurally disqualifying for Laravel. The bundle registers via Symfony's Bundle class and DI extension, wires an authentication provider into the Symfony security firewall, and is configured through a ma27_api_key_authentication root in Symfony's config tree. Laravel exposes none of those primitives — no bundles, no firewall factories, no AuthenticationProviderInterface. The release notes describe "improvements regarding the internal design," which, if they mean migration onto the post-5.3 / 6.0+ Symfony security contracts, would make the package more Symfony-idiomatic and therefore no closer to Laravel. This is unverified — the notes contain no technical detail and the changelog contents were not supplied.

Integration feasibility. Still port, do not install, at the same cost profile. The reusable surface remains small: a key entity/model, a generator, a verification routine, and a request-side auth hook. The alpha status does not reduce porting effort; it slightly increases it, because the reference implementation is now a moving target with no backwards-compatibility promise between pre-releases. Pin the exact tag (2.0.0-alpha1) or commit SHA used for the read, and record it in the spike memo so the port is traceable to a known source. The Laravel-native build is unchanged: migration + Eloquent model for keys, Str::random/random_bytes for generation, hash('sha256', …) with hash_equals() for constant-time verification, a custom guard registered via Auth::extend, and an auth.apikey middleware.

Technical risk. Still high and concentrated on the authentication path, with one risk retired and two added.

Retired (partially): abandonment. There is an active maintainer and a release cadence again. Do not over-read this — one alpha after a multi-year gap is an intent signal, not a support commitment.

Added:

  • Alpha churn. No BC guarantee across alphas/betas. If any code is carried over verbatim, pin and track; expect to re-read the source at GA.
  • Docs drift, self-disclosed. The notes state docs may be out of date. Any conclusion drawn from documentation rather than source is unreliable right now — the spike must read code, not README.

Unchanged and still to be validated in the spike:

  • PHP version floor/ceiling in composer.json — still the fastest way to end the investigation.
  • RNG quality for key generation — random_bytes/openssl_random_pseudo_bytes or better only.
  • Storage of secrets — hashed at rest, or a finding.
  • Comparison safety — hash_equals only.
  • Lifecycle gaps — expiry, revocation, rotation, scopes, last_used_at are still expected to be net-new work regardless of the package.
  • Framework contract drift — now possibly addressed by 2.0, which is the one thing about this release that would matter technically, and the one thing the notes do not tell us.

Key questions for the spike — updated.

  1. What does the 2.0.0 changelog actually list? Specifically: minimum PHP, supported Symfony versions, and whether it targets the 6.x security contracts. (Blocking — this determines whether the reference code is even instructive.)
  2. What is the LOC/class-count delta between 1.x and 2.0.0-alpha1, and how much is Symfony plumbing versus key logic?
  3. Does 2.0 add any of the missing lifecycle features — expiry, revocation, rotation, scopes, multiple keys per user?
  4. What RNG and hashing primitives are used, and are comparisons constant-time?
  5. Is the license header clean across all files (MIT declared — confirm no vendored code under a different license), and has the license changed on the 2.0 branch?
  6. Is the maintainer signalling a GA timeline, or is this an indefinite alpha? A stalled alpha is worse than a clean archive for planning purposes.
  7. Do we need self-service keys (user-generated in a UI) or admin-issued? Determines whether we need the generator at all.

Integration Approach

Stack fit. Unchanged: PHP 8.x-era Symfony bundle against Laravel 10/11. The language is shared; essentially nothing else is. Cross-framework read-and-port, not an integration. The 2.0 line, if anything, deepens the Symfony coupling by modernizing against newer Symfony contracts.

Migration path. Do not add this to composer.json. An alpha-status package on the authentication path is a worse supply-chain decision than the archived version was, because an alpha implies imminent breaking change rather than stable stagnation. Instead:

  1. Fork under MIT, pinned to 2.0.0-alpha1 — or simply copy the ~5 relevant classes into a scratch branch as a reference. Retain attribution in a NOTICE or file header if any code is carried over verbatim, and note the source tag.
  2. Extract the design, not the code. Capture the key-storage schema shape, the generate/verify flow, and the request-lifecycle hook. Discard the Symfony wiring entirely. Re-read at GA if the changelog shows the key logic changed materially between alpha1 and GA.
  3. Reimplement natively as a first-party module: api_keys table (id, keyable morph, name, prefix, hash unique-indexed, scopes json, expires_at, last_used_at, revoked_at, timestamps); ApiKey model; ApiKeyGuard implementing Illuminate\Contracts\Auth\Guard; AuthenticateApiKey middleware aliased in bootstrap/app.php; a php artisan api-key:issue command for ops.
  4. Adopt framework-native primitives rather than the bundle's: Laravel's Hash/hash_equals, Str::random(48), config publishing, and the existing rate limiter (RateLimiter::for('api')) keyed on the API key rather than IP.

Compatibility. Assume incompatibility until proven. The 2.0 branch may well widen the supported-Symfony range while remaining entirely outside Laravel's orbit; treat "supports Symfony 6" as irrelevant to our decision. The only compatibility posture that survives the next Laravel major is a rewrite of the internals with zero shared runtime dependencies.

Sequencing — one step amended.

  1. Week 1 — spike (1 eng-day). Answer the seven questions above, starting with the changelog. Write a one-page memo with a build-vs-port recommendation (expected outcome: build).
  2. Week 1 — design review. Lock key format (prefixed, e.g. pk_live_… for identification + secret hash), hashing scheme, scope model, expiry/rotation policy, revocation semantics. Sign off with security.
  3. Sprint 2 — build. Model + migration + guard + middleware + Artisan commands; feature-flagged and off by default.
  4. Sprint 2 — test. Unit tests for generation entropy, constant-time comparison, expiry, revocation, scope enforcement; one integration test per protected route; a negative test proving a revoked key is rejected within the same request cycle.
  5. Sprint 3 — rollout. Shadow-mode log-only middleware on a low-risk internal API for one week, then enable per-route. Establish a rotation runbook before the first external consumer gets a key.
  6. Opportunistic — re-check at 2.0 GA. If GA lands with lifecycle features we priced as net-new (scopes, expiry, revocation), harvest the design for those specifically. Do not change the runtime dependency decision.

Operational Impact

Maintenance. Ownership still transfers to us on day one, because we will not be installing the package. The maintenance outlook for the upstream project has improved from "dead" to "pre-release revival," which matters for the reference implementation only: it means the source we read will likely still exist and get fixes, so the code we port is less likely to be a snapshot of an abandoned approach. It does not change our upkeep budget — ~2–4 engineer-days per year for our own module, driven mostly by Laravel major upgrades.

Support. Revised upward, cautiously. There is now a maintainer and a release channel; the previous "no upstream maintainer, no community" assessment is no longer accurate as written. But 8 stars and 0 dependents still mean no third-party corpus, no Stack Overflow history, and no ecosystem of write-ups — 2.0 being an alpha means the small corpus that does exist may describe the old architecture and be actively misleading. Treat upstream as a courtesy channel, not a support contract. Our API-key module needs a named owner in the on-call runbook.

Scaling. Unchanged and independent of the release, since we are not running their code. Verification is on every authenticated request, so the hot path must be O(1): a unique index on the key hash, lookup by hash rather than iterating candidates, and a Redis cache for key→principal resolution with explicit invalidation on revoke. Plan a short TTL (30–60s) with revoke-on-write invalidation and accept the bounded revocation window as a documented, reviewed tradeoff. last_used_at writes must be sampled or queued, never per request, or the read path becomes a write path under load. Note: if the 2.0.0 "performance improvements" are meaningful, they accrue to Symfony users; they do not transfer to a native Laravel implementation.

Failure modes to design against.

  • Weak RNG in ported code → guessable keys. CSPRNG only, plus a startup assertion/test.
  • Non-constant-time comparison → timing oracle. hash_equals only; lint rule or review checklist.
  • Missing/incorrect index → table scan and latency cliff as key count grows. Load test with 1M keys before launch.
  • No rotation or revocation tooling → a leaked key cannot be retired without a deploy. Ship revoke/rotate commands and a runbook before the first external key is issued.
  • Long-lived worker state (Octane/queues) → a revoked or expired key continues to authenticate inside a warm worker. Stateless guard, no in-process principal cache, or cache with hard TTL.
  • Middleware ordering → API-key auth running before or after throttle incorrectly, yielding unthrottled authenticated traffic. Explicit route-group ordering and a test.
  • Clock skew on expires_at → premature or late expiry across nodes. UTC everywhere, small grace window.
  • New: porting from a moving target → carrying over alpha code that changes at GA. Pin the source tag in the fork and record it; re-diff at GA before shipping anything copied verbatim.

Ramp-up. Shallow for anyone who knows Laravel — the ported surface is tiny and uses framework-native primitives. The real cost is un-learning the Symfony idioms, which is why reading the bundle is a spike activity, not a training investment. 1 engineer-day to reach confident comprehension of the original, 2–3 days for a mid-level engineer to own the first-party replacement. The organizational risk is unchanged and arguably sharpened: a fresh 2.0.0 release creates a stronger false signal that API-key auth is "solved and maintained," when the package still supplies only a fraction of a production key system (rotation, scopes, expiry, audit, revocation) and supplies it in the wrong framework. The alpha tag mitigates this only for readers who get past the headline.

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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package