flint/antenna
Antenna is a Laravel package that simplifies receiving, validating, and processing incoming webhooks. It provides a clean, testable way to connect third-party services to your app with configurable endpoints and handlers, so you can focus on business logic instead of boilerplate.
Antenna is a Symfony 2 bundle, not a Laravel package — the mental mapping is: Symfony firewall listener ≈ Laravel guard/middleware, Symfony SecurityContext ≈ Auth::user(), Antenna's token service ≈ the encode/decode half of tymon/jwt-auth. Budget an hour for that translation before touching code.
Minimal path:
composer require flint/antenna on a modern stack will almost certainly fail. The 2015 release constrains PHP (~5.4/~5.5) and Symfony (~2.3–~2.7). Confirm with composer why-not flint/antenna and decide early whether you are vendoring/forking or walking away — this decision dominates everything else.app/AppKernel.php (new Flint\AntennaBundle\FlintAntennaBundle()) and import its routing only if it ships controllers.DependencyInjection/Configuration.php — that file is the real README. Expect keys for secret/key, algorithm (HS256), token TTL, and the user provider/claim mapping.firewall listener key). Almost every integration question resolves to one of those two.First use case: a POST /login controller that validates credentials manually, loads the user, and returns a signed token; plus a stateless firewall that accepts Authorization: Bearer <token> on your API paths and rejects everything else. Get that loop working end-to-end with a hardcoded user before wiring a real user provider.
Stateless API firewall. Define a separate firewall for your API prefix with stateless: true, anonymous: false, and Antenna's listener as the sole authentication mechanism. Keep your existing form_login firewall for the browser app and share the user provider — this hybrid (session for humans, JWT for machines) is the common real-world shape and is what the bundle was built for.
Custom listener factory. Antenna exposes a firewall listener key; the factory reads check_path, header name, and token extraction rules from security.yml. If you need the token in a query param or a non-standard header, the extension point is a custom listener/factory, not a config flag.
Token issuance in a controller/service. Resolve the token manager from the container and pass a payload (subject identifier, roles, expiry). Keep claims thin: an ID plus expiry. Roles in the token drift from the database the moment someone is demoted, so load roles from the user provider per request unless you have measured a reason not to.
Decorate, don't fork. If you need extra claims or a refresh flow, decorate the token service (decorates: in services.yml) rather than editing vendor code — that keeps the fork small if you must maintain it.
Testing. Functional tests are cheap here: build a token with the same service in a test helper and pass it as a header to the kernel browser client. Assert 401 on missing/expired/garbage tokens and 200 with a valid one; those three cases catch most misconfiguration.
Migration pattern if you stay. Isolate all Antenna calls behind one small TokenIssuer/TokenAuthenticator service pair you own. That makes the eventual swap to lexik/jwt-authentication-bundle (or firebase/php-jwt used directly, which is what most Laravel shops reach for) a two-file change.
firebase/php-jwt releases accepted alg: none, and algorithm-confusion bugs were common in that era. Verify explicitly that the algorithm is pinned during decode and never trusted from the token header.Authorization is dropped by CGI/FastCGI. Add SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 on Apache, or fastcgi_param HTTP_AUTHORIZATION $http_authorization; on nginx.stateless: true is not enough to stop sessions. Other listeners and framework.session can still start a session, which makes tokens appear to work while you are actually being authenticated by a cookie. Test with cookies cleared.security: false off the API firewall. A firewall without a listener short-circuits and your token code never runs; you get 200s with no user, or confusing 403s from access_control.AuthenticationException (401) via a configured entry point; insufficient role is AccessDeniedException (403). Antenna-era bundles often left the entry point unset, producing HTML redirects to a login page for API clients. Set the entry point explicitly.parameters.yml. Move it to an env var, and note that rotation invalidates every outstanding token with no grace window — plan a dual-key verify period if you rotate.logger output on the security channel; log the decoded claim set (never the token or secret) at debug level. For fast triage, decode the token payload by hand and compare exp/sub against the clock before suspecting the bundle.sub, cache it) → custom listener factory → patch the fork. Anything below the first two means you now own the maintenance.How can I help you explore Laravel packages today?