nette/security
Nette Security is a compact PHP library for authentication and authorization: secure password hashing (bcrypt/argon2), user identities and login, role and permission checks, and CSRF protection. It works standalone or as part of the Nette Framework.
Architecture fit
nette/security is a Nette Framework component: its wiring lives in SecurityExtension (a Nette DI compiler extension), its session persistence depends on nette/http (SessionStorage, CookieStorage), and its UI helper (UserPanel) targets the Tracy debug bar. None of that maps onto Laravel's container, middleware pipeline, or session guards.Illuminate\Auth), gates/policies, Role-style ACL packages (Spatie Permission), and session drivers cover the same ground with first-class framework contracts. Adopting nette/security means maintaining a translation layer between two security models — high surface area for low marginal value.Authenticator/IdentityHandler/SimpleIdentity contracts, the Authorizator (ACL roles/resources/permissions) core, and the Passwords object. These are small, mostly framework-agnostic interfaces that could be wrapped as Laravel services, but doing so discards the package's DI conveniences — i.e., you pay the integration cost without the ergonomic payoff.Integration feasibility
Nette\Security\UserStorage backed by Laravel's Session/Auth session, and reconcile sliding-expiration semantics with Laravel's SESSION_LIFETIME / expire_on_close.IIdentity to/from Illuminate\Contracts\Auth\Authenticatable so Blade @auth, Gate::allows, and policy discovery don't fork into two truths.Authorizator becomes the system of record for permissions, or a secondary check beneath Laravel gates. Two permission engines is a compliance and debugging hazard.Technical risk
Auth::user(), stale identity caches (User::refreshStorage() exists precisely because caching bites), and permission checks that disagree. This is a security-review blocker, not a code-hygiene nit.NOASSERTION on a security-critical dependency means legal has to hand-verify the Nette license (BSD-3-Clause in practice) before adoption. Non-trivial for enterprise procurement; trivially resolvable, but it blocks the critical path.I*-prefix debt. This is a maintained library, not abandoned — which makes the risk integration, not longevity.IUserStorage, Passwords static→object). Semver discipline is fine but majors move; our bridge layer must be pinned and regression-tested.getGuestIdentity() is genuinely useful for anonymous-with-roles modelling, but must be explicitly reconciled with Laravel's guest handling or you get phantom roles on unauthenticated requests.Key questions
nette/security ACL, or Laravel gates/policies? Pick one; the other becomes a projection.UserPanel/Tracy in scope? If not, we're importing debug-bar code we'll never run — factor that as dead weight in the dependency review.NOASSERTION? Escalate immediately if adoption is serious — legal review is the longest-lead item and gates the whole plan.Stack fit
nette/security with a caret constraint and treat the bridge as a first-party package under our packages/ or a private Composer repo — do not patch vendor.NetteSecurityBridgeServiceProvider) that binds Nette\Security\User, Authenticator, Authorizator, and a custom UserStorage into the container. This keeps Nette's DI extension entirely out of the app — we never load SecurityExtension.UserStorage delegates to Illuminate\Session\Store; Passwords is replaced by Hash::make/Hash::check unless we need Argon2id parameter control the framework doesn't expose. Prefer framework primitives wherever the package is merely adequate.Gate definitions (Gate::define driven by Authorizator::isAllowed) so existing can: middleware, Blade directives, and policy discovery keep working unchanged.Migration path
Authorizator as a shadow evaluator — compute both Laravel gate and Nette ACL decisions, log disagreements, enforce nothing. This is the cheapest way to discover semantic gaps before they become incidents.Auth::user() as the source for identity; map into SimpleIdentity on read. Reverse the direction only if the estate-wide ACL requirement is confirmed.Compatibility
SESSION_LIFETIME. Document the chosen behaviour in code and in the ops runbook; ambiguous expiry rules are an audit finding.getGuestIdentity() or Laravel's guest middleware owns anonymous roles. Two answers = phantom permissions.$persistIdentity: new in v3.2.4 and genuinely useful for personalisation-after-logout; align it deliberately with our data-retention and GDPR posture rather than accepting the default.Sequencing
UserStorage, expiry-semantics test suite, no ACL work. This de-risks the dominant unknown.Authorizator alongside Gate, disagreement logging, one internal surface only.IIdentity ↔ Authenticatable, guest identity decision, cache-invalidation tests.Maintenance
nette/security pulls nette/utils and nette/http (session/request abstractions we partly bypass anyway). Budget quarterly upgrades and track Nette majors for BC breaks (v3.x has already broken twice).nette/phpstan-rules as a mandatory build step and ships improved phpDoc types; our bridge can inherit level 8+ cleanly. This is a genuine quality argument in favour of the package and worth citing in the ADR.Support
AuthManager resolution and Nette's User/UserStorage/Authenticator triad. That's a real onboarding tax on a team otherwise fluent in Laravel.Scaling
User caches identity and auth state (v3.0.3) to avoid repeated storage calls — good for latency.UserStorage scales fine; the package's cookie storage is not a fit for multi-instance deployments. Enforce the session-driver matrix in CI.User::refreshStorage() must be wired into role/permission mutations, or users retain stale privileges until session expiry — which, post-v3.2.3, may be longer than expected because expired sessions no longer slide.Failure modes
User identity. Mitigate with mandatory refreshStorage() on mutation plus an admin "force re-auth" control.composer update in CI.NOASSERTION means we must assert the licence text in our SBOM rather than trust the badge.Ramp-up
User → UserStorage → Authenticator, plus Authorizator); the API surface is small and the docs are decent.How can I help you explore Laravel packages today?