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

Symfony Url Token Bundle Laravel Package

hprotravel/symfony-url-token-bundle

A Symfony bundle for creating and validating signed URL tokens, helping secure temporary links, protect routes, and enable token-based access without exposing raw identifiers. Simple service integration and configuration for Symfony apps.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package, so "getting started" means two different things depending on your situation: dropping it into a Symfony app, or evaluating whether the pattern is worth reimplementing in Laravel.

First steps in a Symfony app

  1. composer require hprotravel/symfony-url-token-bundle — the package is on a private Bitbucket, so you'll likely need a repositories entry of type vcs plus credentials (SSH key or Bitbucket app password) in auth.json. Expect Composer to fail on a clean machine without those; that's the first thing to verify in CI.
  2. Register the bundle in config/bundles.php (Symfony Flex may do this automatically if the bundle ships a recipe — a 0-star Bitbucket package almost certainly does not, so add it manually).
  3. Look here first: DependencyInjection/Configuration.php inside the vendor directory. That file defines every config key the bundle accepts. For a URL-token bundle you're looking for three things: the signing secret/key, the token TTL, and any route/path scoping. Then read DependencyInjection/*Extension.php to see which services get registered and under what IDs — that tells you what's autowirable.
  4. Dump the container (bin/console debug:container --show-private | grep -i token) to confirm the generator/validator service IDs before writing any code against them. Guessing service IDs is the #1 way to burn an hour on a low-documentation bundle.

First use case

The canonical one: a time-limited, tamper-proof URL. Password-reset links, signed file-download links, "magic link" logins, one-click unsubscribe, or share links to a private resource. The shape is always the same — generate a URL containing a token bound to some payload (resource ID, user ID, expiry), then validate that token when the request comes back in.

Laravel equivalent, for context

Laravel already ships this as signed URLs (URL::temporarySignedRoute(), the signed middleware). If you're a Laravel dev reading this bundle for inspiration, you probably don't need it — you need signed middleware plus a hasValidSignature() check. Keep reading only if you need custom payload binding or token reuse semantics that signed URLs don't give you.

Implementation Patterns

Pattern 1 — Generate-then-redirect

The most common flow. Your controller (or a console command, or a queued job) calls the bundle's token generator with a payload and TTL, receives a URL, and hands it to the user via email or redirect.

// Pseudo-shape; confirm method names via debug:container
$url = $tokenGenerator->generate('download_file', ['id' => $file->getId()], '+30 minutes');
return $this->redirect($url);

Keep generation in a dedicated service (DocumentLinkService, MagicLinkIssuer), not inline in controllers. You will regenerate these links from three or four places — mailers, admin panels, API endpoints — and the TTL policy needs to live in exactly one spot.

Pattern 2 — Validate in an event subscriber, not in every controller

Wrap validation in a kernel.request listener that inspects the route and bails early with a 403/410 if the token is missing, malformed, expired, or doesn't match the expected resource. This keeps controllers clean and gives you one place to log failures. Register the listener only for routes that need it (via a route attribute convention or an explicit route whitelist) so you don't pay the cost on every request — and more importantly so you don't accidentally block public routes.

Pattern 3 — Bind the token to a resource, not just to "valid"

A bare "is this token valid" check is a horizontal-privilege bug waiting to happen: a token minted for invoice #1 will happily unlock invoice #2 if the controller trusts the URL's ID param. Always include the resource identifier in the signed payload and compare it against the route parameter server-side. Treat the URL's other query params as untrusted.

Pattern 4 — One-time vs. reusable

Decide explicitly per use case:

  • Reusable until expiry — share links, download links. Cheap, stateless, but a leaked URL works until TTL.
  • Single-use — password resets, magic logins. Requires a nonce stored in the DB (or cache) and marked consumed on first validation. The bundle may or may not support this; if not, layer it yourself by storing the token hash with a used_at column.

Pattern 5 — Integration with Symfony's DI and config

Inject the generator as a normal autowired service and keep the TTL in config/packages/*.yaml rather than hardcoded, so staging and prod can differ. If the bundle exposes an interface, type-hint the interface in your services — it makes swapping in your own implementation (or a test double) trivial.

Pattern 6 — Testing

Generate a token in a unit test, assert it validates; then assert it fails after TTL (inject a clock or use a token with a negative TTL rather than sleep()), fails after payload tampering, and fails with a truncated/modified signature. In functional tests, hit the route with a generated URL and expect 200, then hit it with a mangled token and expect 403.

Gotchas and Tips

It's a Symfony bundle — the Laravel cost is real. No service provider, no facade, no config/url-token.php. You'd be porting the concept, not the code. Weigh that before adding a private-repo dependency to a Laravel project; Laravel's native signed URLs cover ~90% of cases.

Private Bitbucket repo = supply-chain and onboarding friction. Every developer and every CI runner needs credentials. There's no Packagist metadata, no security advisories, no composer audit coverage. If this bundle ends up in a critical path, consider vendoring the handful of classes you actually use into your own App\Support namespace so you're not hostage to a repo that could go dark.

Zero stars, zero dependents, zero public documentation. Read the source. Budget an hour. Prioritize, in order: Configuration.php (config keys), *Extension.php (service IDs), the token generator class (signing algorithm, TTL semantics), the validator/listener (what it actually checks). Skim composer.json for the PHP and Symfony version constraints — an unmaintained bundle often pins old Symfony majors and will block an upgrade.

Verify the signing algorithm yourself. Look for hash_hmac with hash_equals in the verification path. Anything using == for signature comparison, or md5/sha1, is a red flag — you're looking at a security-sensitive primitive and the package has no public review. If it's weak, wrap or replace it.

Expiry semantics are ambiguous until you read the code. Does the TTL mean "token expires at" or "token valid for"? Is expiry encoded in the token or stored server-side? Is it seconds or a strtotime-style string? Getting this wrong means links that live 30 seconds or 30 days instead of 30 minutes. Write a test that pins the behavior.

Clock skew and timezones. If expiry is a Unix timestamp, ensure time() and the stored value are both UTC. If you're behind a load balancer with skewed clocks across app servers, links can appear expired on one node and valid on another. Keep TTLs generous enough to absorb a few seconds of skew.

URL encoding bites. Tokens containing +, /, or = in query strings get mangled the moment someone forwards the email through a client that re-encodes. Prefer base64url (no padding) or hex. Test with a token that contains every special character.

Logging failures is where the debug time is saved. Log the reason (missing / expired / bad signature / wrong resource) at info or debug, but never log the full token or the secret — they're bearer credentials. Log a truncated hash instead.

Extension points to prefer. If the bundle exposes interfaces for the token generator or validator, bind your own implementation in services.yaml rather than patching vendor code. If it doesn't, the cleanest extension is a thin decorator service around the native one that adds logging, nonce tracking, or payload normalization — that survives a composer update.

Don't rely on it for authorization. A valid URL token answers "did we mint this link," not "is this user allowed to see this record." For anything multi-tenant or role-sensitive, still run your normal authorization check after token validation. The token gets you past the door; it doesn't decide what's in the room.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource