sportnco/token-manager-bundle
A Symfony bundle for managing API tokens: create, store, validate, and revoke tokens with configurable lifetimes and persistence, plus integration with Symfony's security layer for authenticated client and service-to-service requests.
First, confirm the impedance mismatch. sportnco/token-manager-bundle is a Symfony bundle (per its description and the Bundle suffix). Laravel does not consume Symfony bundles — there is no package:discover hook, no Illuminate\Support\ServiceProvider, and no config/*.php merge. Before writing any application code, check composer.json in the repo for:
"type": "symfony-bundle" — confirms it only wires into a Symfony Kernel.require on symfony/framework-bundle, doctrine/orm, or symfony/security-bundle — these tell you how tightly coupled the token storage is.autoload.psr-4 namespace for the bundle class (needed to register it in config/bundles.php).With zero stars and zero dependents, treat the package as reference material first, dependency second. The realistic day-one decision is one of three:
Where to look first, in order:
README.md — the only place the config tree and the "happy path" service name are usually documented. If it is absent or thin, that is a signal on its own.src/DependencyInjection/*Extension.php — this is the authoritative list of configuration keys, because the extension's load()/Configuration class is the schema. Read it before you read any docs.src/DependencyInjection/Configuration.php — the nested tree, defaults, and which nodes are isRequired().src/ top level for the nouns: expect something like a Manager/TokenManager service, a Token entity or model interface, and a generator/hasher. That triad is the whole package.src/Resources/config/ (or config/) — services.xml / services.yaml. Service IDs, aliases, and whether anything is public are all here.Canonical first use case — issue a token, persist it, validate it once:
// Symfony side (if you are actually running Symfony)
$token = $tokenManager->create($user, ttl: new \DateInterval('PT1H'));
// hand $token->getValue() to the user; store only the hash
$isValid = $tokenManager->consume($presentedValue);
If you are porting to Laravel, the equivalent shape is a TokenService bound in a service provider, a tokens table via a normal Laravel migration, and a Token::query()->where('hash', hash('sha256', $presented)) lookup — the bundle gives you the design, not the code.
Pattern 1 — Symfony-native wiring (only if the host app is Symfony).
// config/bundles.php
Sportnco\TokenManagerBundle\TokenManagerBundle::class => ['all' => true],
# config/packages/token_manager.yaml
token_manager:
# keys come from Configuration.php, not from guesswork
ttl: 3600
Then inject the manager by its service alias rather than by class name — bundles frequently alias an interface to the concrete manager, and autowiring by interface is the stable contract.
Pattern 2 — Port to Laravel (the likely path for your day-to-day). Keep the bundle's separation of concerns but use Laravel idioms:
TokenManager as a singleton in register(), publish config in boot().Configuration tree with config/token-manager.php, keys mirroring the bundle's nodes so the two apps stay conceptually aligned.id, tokenable_type/tokenable_id (or your FK), hash, expires_at, consumed_at, plus a unique index on hash.app() inside methods, or you lose the ability to swap the generator in tests.Pattern 3 — Token lifecycle as an explicit state machine. Whatever the package's internal API, model the lifecycle yourself and keep the manager thin:
random_bytes(32)), store only a hash, return the plaintext once.lockForUpdate) so two concurrent requests cannot both redeem.Pattern 4 — Scope and purpose. Most real token systems need a type/ability column (password reset vs. email verification vs. API token). If the bundle does not offer scopes, add the column yourself before the table has data — retrofitting a scope onto an unscoped token table is a migration with downtime.
Pattern 5 — Integration points. Register a listener/observer on "token consumed" so audit logging, session revocation, and notification happen outside the manager. This is the extension point the bundle is most likely to expose (tagged services or events); use it rather than subclassing the manager.
require lists doctrine/orm, pulling it into a Laravel app drags in a second ORM, a second connection strategy, and a second migration story. That is usually a worse trade than reimplementing ~150 lines.$tokenManager autowiring depends on an alias in the bundle's service config. If bin/console debug:container TokenManager finds nothing, the alias is missing and you must wire an explicit services.yaml entry.token_manager:), not at the top level. A misplaced key is silently ignored unless the Configuration tree declares it — which is why you read Configuration.php first.bin/console cache:clear after every config edit. Symfony caches the compiled container; a stale cache will make you debug a config change that did apply.doctrine:schema:update --force in dev and a hand-written migration for production. In Laravel, always a real migration — never sync from a mapping.value column, it was designed for convenience over safety. Add a hash column and compare with hash_equals(), not ===.datetime is naive; store UTC, compare UTC, and test the boundary (exactly expires_at) explicitly.SELECT ... FOR UPDATE (or Laravel's lockForUpdate()); otherwise a one-time token is redeemable twice under load.random_bytes/random_int, not mt_rand/uniqid. Read the expiry check yourself. This is a 20-minute review that replaces a year of assumed trust."sportnco/token-manager-bundle": "dev-master#<sha>" or an exact tag) and vendor-review on upgrade; low-traffic packages rarely get security patches.How can I help you explore Laravel packages today?