nette/security
Security utilities for Nette apps: authentication and authorization helpers, user identity and roles, access control checks, and related infrastructure for building secure login flows and protecting resources with a consistent API.
Install the Package
composer require nette/security
Note: Since this is Nette-focused, you’ll need to manually integrate it with Laravel’s DI container.
Configure Basic Authentication
Add to config/services.php:
'security' => [
'authentication' => [
'storage' => \Nette\Security\SessionStorage::class,
'persistIdentity' => true, // Default: true
],
'roles' => ['admin', 'editor', 'user'],
'resources' => ['dashboard', 'profile', 'settings'],
],
Create a Simple Authenticator
use Nette\Security\Authenticator;
use Nette\Security\Identity;
class UserAuthenticator implements Authenticator
{
public function authenticate(array $credentials): Identity
{
$user = User::where('email', $credentials['email'])->first();
if (!$user || !password_verify($credentials['password'], $user->password)) {
throw new \Nette\Security\AuthenticationException('Invalid credentials.');
}
return new \Nette\Security\SimpleIdentity($user->id, $user->roles);
}
}
Register Services in AppServiceProvider
public function register()
{
$this->app->singleton(\Nette\Security\User::class, function ($app) {
$authenticator = new UserAuthenticator();
$storage = new \Nette\Security\SessionStorage($app['session.store']);
return new \Nette\Security\User($authenticator, $storage);
});
}
First Use Case: Protect a Route
Route::get('/dashboard', function () {
$user = app(\Nette\Security\User::class);
if (!$user->isLoggedIn()) {
abort(403);
}
return view('dashboard');
})->middleware('auth');
$user = app(\Nette\Security\User::class);
$user->login($credentials, $authenticator);
$user->logout($clearIdentity = true); // Default: true
$user->getGuestIdentity(); // Returns a SimpleIdentity for anonymous users
if ($user->isInRole('admin')) {
// Admin-only logic
}
$authorizator = $user->getAuthorizator();
if ($authorizator->isAllowed('admin', 'dashboard', 'view')) {
// Grant access
}
$authorizator->addPermission('admin', 'dashboard', 'edit', function ($user) {
return $user->isInRole('superadmin');
});
$storage = $user->getStorage();
$storage->setExpiration(new \DateTime('+1 hour'));
$user->setExpiration(new \DateTime('+30 minutes'), true); // Clear identity
$passwords = app(\Nette\Security\Passwords::class);
$hash = $passwords->hash('plaintext');
if ($passwords->verify('plaintext', $hash)) {
// Valid
}
Middleware for Authentication:
class NetteAuthMiddleware
{
public function handle($request, Closure $next)
{
$user = app(\Nette\Security\User::class);
if (!$user->isLoggedIn()) {
return redirect()->route('login');
}
return $next($request);
}
}
Leverage Laravel’s Session:
$storage = new \Nette\Security\SessionStorage($request->getSession());
Custom Identity Storage:
class DatabaseStorage implements \Nette\Security\UserStorage
{
public function getIdentity($id)
{
return User::find($id)?->toIdentity();
}
// ... other methods
}
Event Listeners:
$user->onAuthenticate[] = function ($user, $authenticator) {
// Post-auth logic (e.g., log activity)
};
Dynamic Role Assignment:
$user->getRoles(); // Returns array|string
$user->setRoles(['admin', 'editor']); // Update roles
Guest Role Fallback:
$user->getRoles(); // Returns ['guest'] if not logged in
Session Storage Assumptions:
CookieStorage for stateless setups:
$storage = new \Nette\Security\CookieStorage($request, 'auth_token');
Identity Persistence:
persistIdentity (v3.2.4+) defaults to true, meaning identities linger after logout for personalization (e.g., "Welcome back, John"). Set to false to fully clear:
'authentication' => [
'persistIdentity' => false,
]
Guest Identity Quirks:
getGuestIdentity() in a custom IdentityHandler:
class CustomIdentityHandler implements \Nette\Security\IdentityHandler
{
public function getGuestIdentity(): ?\Nette\Security\IIdentity
{
return new \Nette\Security\SimpleIdentity('guest', ['guest']);
}
}
BC Breaks in v3.x:
IUserStorage was removed in v3.1.0. Migrate to UserStorage:
// Old (v2.x)
$storage = new \Nette\Http\UserStorage();
// New (v3.x)
$storage = new \Nette\Security\SessionStorage($session);
Password Hashing:
$passwords = new \Nette\Security\Passwords();
$passwords->setAlgorithm(\Nette\Security\Passwords::PASSWORD_ARGON2I);
Check Identity State:
var_dump($user->isLoggedIn(), $user->getIdentity(), $user->getRoles());
Inspect Storage:
$storage = $user->getStorage();
$storage->getState(); // Returns session/cookie data
Enable Tracy (Nette Debugger):
$user->getAuthenticator()->onAuthenticate[] = function ($user, $authenticator) {
\Tracy\Debugger::barDump($user->getIdentity());
};
Log Exceptions:
try {
$user->login($credentials, $authenticator);
} catch (\Nette\Security\AuthenticationException $e) {
\Log::error('Auth failed: ' . $e->getMessage());
}
Custom Authenticators:
class ApiAuthenticator implements \Nette\Security\Authenticator
{
public function authenticate(array $credentials): \Nette\Security\Identity
{
// API token validation logic
return new \Nette\Security\SimpleIdentity($userId, ['api_user']);
}
}
Dynamic Authorizators:
$authorizator = new \Nette\Security\Authorizator();
$authorizator->addResource('admin', [
'dashboard' => ['view', 'edit'],
'users' => ['list', 'create'],
]);
Override Storage:
class DatabaseUserStorage implements \Nette\Security\UserStorage
{
public function getIdentity($id)
{
return User::find($id)?->toIdentity();
}
public function saveIdentity(\Nette\Security\Identity $identity)
How can I help you explore Laravel packages today?