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

Security Laravel Package

iseazy/security

A Laravel security package from Iseazy offering reusable helpers and hardening utilities for PHP applications, helping teams centralize common protections and keep authentication and authorization behavior consistent across projects.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is iseazy/security, published from isEazy-Engage/iseazy-security-bundle. The repository name ends in -bundle, which is the strongest signal available: this is a Symfony bundle, not a framework-agnostic library and not a Laravel package. Treat every step below as "verify, then wire", because with 0 stars and 0 dependents there is no ecosystem of blog posts or Stack Overflow answers to fall back on.

1. Confirm the shape of the package before designing anything around it.

composer require iseazy/security
cat vendor/iseazy/security/composer.json   # PHP + symfony/* constraints, autoload prefix, extra.symfony
ls vendor/iseazy/security/src

Read composer.json first. It tells you three things you cannot guess:

  • the PHP and Symfony version ceiling (a bundle released against Symfony 6.4 will fight you on 7.x),
  • the PSR-4 namespace you will import in use statements,
  • whether it registers itself via extra.symfony / Symfony\Bundle\FrameworkBundle flex recipe or expects manual registration.

2. Register the bundle. Find the class ending in Bundle and add it to config/bundles.php:

// config/bundles.php
return [
    // ...
    Iseazy\Security\IseazySecurityBundle::class => ['all' => true],
];

If the namespace differs from what you assumed, that is your first integration bug — the bundle class is the single source of truth for the namespace, not the Composer package name.

3. Find the extension alias, then write the config file. The alias is whatever getAlias() returns (or the root node name in src/DependencyInjection/Configuration.php). Confirm it rather than guessing:

bin/console debug:config iseazy_security
bin/console config:dump-reference iseazy_security

config:dump-reference is the fastest way to learn the entire public surface of an undocumented bundle — it prints the config tree with defaults and comments.

4. Where to look first, in priority order.

Location What it tells you
README.md May be sparse or internal-only; check last-updated date
src/DependencyInjection/Configuration.php The real API: every option and default
src/DependencyInjection/*Extension.php Which services are conditionally registered and under what config
src/Resources/config/services*.yaml Service IDs, tags (security.authenticator, security.voter), and aliases you can override
src/Security/ Authenticators, user providers, voters, password hashers — the actual behaviour
src/Attribute/ or src/Annotation/ Whether it offers PHP-attribute-based authorization

5. First use case to attempt. Do not start by rewriting your firewall. Pick the smallest observable behaviour:

  • If the bundle ships an authenticator, add it to one non-critical firewall and assert a 401/302 in a functional test.
  • If it ships a voter, apply it to a single controller action and assert 403 for an unauthorized user.
  • If it only ships services (token decoding, signature validation, header parsing), inject one into a single handler and unit-test it in isolation.
// minimal first integration: one action, one assertion
#[Route('/probe', name: 'probe')]
public function probe(): JsonResponse
{
    $this->denyAccessUnlessGranted('ISEAZY_PROBE');
    return $this->json(['ok' => true]);
}

Then bin/console lint:container and bin/console debug:container --tag=security.voter to confirm the bundle actually registered what you think it did.

Implementation Patterns

Config-file-per-environment. Put the shared block in config/packages/iseazy_security.yaml and only the differing keys (keys/secrets/audience/endpoints) in config/packages/{dev,prod}/iseazy_security.yaml. Because the config tree is the bundle's primary API, keeping your usage declarative means an upgrade diff in Configuration.php surfaces immediately as a container lint error rather than a runtime 500.

Firewall integration, not firewall replacement. A bundle like this almost never wants to own your whole security.yaml. Slot its authenticator into the existing firewall and let your app's user provider remain authoritative:

# config/packages/security.yaml
security:
  firewalls:
    api:
      pattern: ^/api
      stateless: true
      custom_authenticators:
        - Iseazy\Security\Security\SomeAuthenticator  # verify the real FQCN
      entry_point: Iseazy\Security\Security\SomeAuthenticator

Two details bite here: the authenticator must appear before the blanket main firewall in ordering terms (firewalls are first-match), and entry_point must be set explicitly or an unauthenticated request falls through to Symfony's default behaviour instead of the bundle's challenge response.

Wrap it behind your own interface. With zero dependents there is no community pressure keeping the public classes stable. Introduce a thin boundary in your app:

interface TokenVerifierInterface { public function verify(string $token): VerifiedIdentity; }

Bind the bundle's service to that interface in services.yaml, and inject the interface everywhere. A breaking change in the bundle then costs you one adapter file, not a codebase-wide rename. This is the single highest-value pattern for a low-adoption dependency.

Decorate for behaviour you need but the bundle lacks. If you need audit logging, clock skew tolerance, or claim normalization, decorate rather than fork:

services:
  App\Security\AuditingVerifier:
    decorates: iseazy.security.some_verifier   # confirm the service id
    arguments: ['@.inner']

Decorate only services the bundle marks public or that are referenced via alias — internal/private services in Resources/config/ are fair game for decoration but not for direct get() from the container.

Override a service by alias, not by editing vendor. Many Symfony bundles define SomeInterface: '@some.concrete.service'. Redefining that alias in your services.yaml swaps the implementation with zero code changes. Check debug:container SomeInterface to see whether the alias exists — if it does, this is your cleanest extension point.

Testing pattern. Because the package's own test suite tells you nothing about your integration, write the contract test yourself:

public function test_unauthenticated_request_is_rejected(): void
{
    $this->client->request('GET', '/api/probe');
    self::assertResponseStatusCodeSame(401);
}

Run this in CI. When you bump the bundle version, this test — not the changelog — tells you whether behaviour changed.

Pin and diff on upgrade. Given the release cadence, use composer require iseazy/security:^X.Y with a caret on a version you have actually tested, and read git diff vPREV..vNEXT -- src/ before bumping. Two minutes of source diff beats an afternoon of debugging.

Gotchas and Tips

The extension-alias mismatch is the #1 first-run failure. "There is no extension able to load the configuration for iseazy_security" means your YAML filename/root key does not match getAlias(). Run bin/console config:dump-reference with no arguments to list every registered alias, and use exactly that.

Package name ≠ namespace ≠ config alias. iseazy/security may map to Iseazy\Security\..., and the config alias may be iseazy_security — or something else entirely. Derive all three from the bundle source, never from the Composer name.

Autowiring is not guaranteed. Internal bundles frequently ship explicit Resources/config/services.yaml definitions with hand-written arguments, and they may not expose interfaces suitable for autowiring. If you get "Cannot autowire service ... argument $x of type string", that service is not autowirable — inject it by its service ID or check whether an interface alias exists. Don't public: true a vendor service to work around this; decorate it.

Stale container after config changes. A new config key that "does nothing" is nearly always a cached container. bin/console cache:clear in the environment that is actually serving the request, not just your shell.

Firewall ordering and entry_point. Symfony evaluates firewalls top-down, first match wins. Adding the bundle's authenticator to a firewall defined below a broader pattern means it never runs. Explicitly set entry_point on stateless API firewalls or unauthenticated requests will not produce the challenge response you expect.

Event-subscriber priority collisions. If the bundle listens on security.authentication.success, security.interactive_login, or lexik_jwt_authentication.on_jwt_created, a subscriber of yours at the same priority can silently win or lose depending on registration order. Inspect with:

bin/console debug:event-dispatcher security.interactive_login

Symfony version constraints are a hard wall. Read composer.json's symfony/* requirements before planning a framework upgrade. A 0-star bundle is not going to be patched promptly for a new major. If you cannot upgrade Symfony without dropping the bundle, know that before the upgrade sprint, not during it.

Debugging checklist, in order:

bin/console lint:container                              # wiring errors
bin/console debug:config iseazy_security                # what config was actually resolved
bin/console debug:container --tag=security.authenticator
bin/console debug:container --tag=security.voter
bin/console debug:event-dispatcher | grep -i security
tail -f var/log/dev.log                                 # channel: security / request

Set monolog.channels: ["security"] to debug when you need the authentication decision trail — Symfony's security logging is verbose and precise, and it is the fastest way to see which listener denied the request.

Prefer attributes over security.yaml for authorization rules if the bundle supports them. Authorization expressed next to the controller action survives firewall refactors; rules buried in YAML do not.

No dependents means no safety net. Assume: the README may be internal-facing, semver may be aspirational, and a patch release may change behaviour. Mitigate with the adapter interface, the pinning strategy, and a small but real integration test suite. Those three things are cheap now and expensive to retrofit.

Extension points ranked by safety: (1) config keys, (2) service alias override, (3) decorator, (4) compiler pass, (5) forking into your own namespace. Stop at the lowest level that solves the problem — with an unmaintained-by-others bundle, escalating to (5) is a signal to reconsider the dependency entirely.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource