leafs/auth Β· framework agnostic
Register, login, sessions or JWTs, roles, permissions and OAuth β on your database, in any PHP app. No identity provider, no monthly bill, no user table you don't control.
$auth = new Leaf\Auth; $auth->connect(['dbname' => 'app', ...]); // the whole sign-in $ok = $auth->login([ 'email' => $email, 'password' => $password, ]); if (!$ok) return $auth->errors(); $user = $auth->user(); $token = $auth->tokens()['access'];
Welcome back
Try a wrong password too β errors are yours to render.
Sign in on the right β the code lights up as it runs. Wrong password shows the real error shape.
The Leaf syntax π
No classes, no setup, no instances to pass around β auth() is simply there in every route, with guards and the signed-in user one call away. Watch it write itself.
POST /register
Mika
mika@leafphp.dev
Password hashed, duplicates rejected, user signed in β one call.
Prefer a class? new Leaf\Auth() gives you the exact same API in any PHP app β see "bring your stack" below.
Somewhere along the way, logging someone in became a platform decision β a vendor, a dashboard, a per-user price, a user table you can't query. Auth is the boring alternative: your database, your users table, a few method calls, done.
What's in the box
Register & login
Two calls, hashed passwords, duplicate checks and readable errors included.
Sessions or JWTs
One config flag switches between cookie sessions and stateless tokens.
Roles & permissions
Define roles once, then ask can(), is() anywhere.
OAuth providers
Google out of the box, any league/oauth2 client through one method.
Your data
Auth writes to a normal table you can query, join, export and back up like anything else. Point it at MySQL, Postgres, SQLite or SQL Server β or hand it a PDO connection you already have open.
$auth->config([ 'db.table' => 'accounts', 'id.key' => 'account_id', 'password.key' => 'secret', 'unique' => ['email', 'username'], 'hidden' => ['field.id', 'field.password'], 'timestamps' => true, ]); // already have a connection? hand it over $auth->dbConnection($pdo);
$auth->createRoles([ 'admin' => ['posts.write', 'users.manage'], 'editor' => ['posts.write'], 'viewer' => [], ]); $user->assign('editor'); $user->can('posts.write'); // true $user->cannot('users.manage'); // true $user->is('editor'); // true
Authorisation
Roles are a map of names to permissions β nothing more. Assign them to users, then ask questions that read like the sentence you were already saying out loud in standup.
Social login
Point auth at your OAuth credentials and it handles the redirect dance, then hands you the same user object as a password login β same table, same tokens, same user() call. Any league/oauth2 provider works through withProvider().
$auth->withGoogle([ 'clientId' => _env('GOOGLE_ID'), 'clientSecret' => _env('GOOGLE_SECRET'), 'redirectUri' => '/auth/callback', ], function ($user) { // same user object as a password login return response()->json($user); });
Batteries where it counts
The parts you'd otherwise write twice a year, already here.
Password changes
Old-password checks and resets, hashed the same way as registration.
$auth->updatePassword($old, $new);
Email verification
Purpose-scoped tokens you can mail out, verify, and check.
$user->generateVerificationToken(); $user->isVerified();
Guards for routes
Decide what happens to guests and to already-signed-in users.
$auth->middleware('auth.required', fn () => response()->redirect('/login'));
Readable errors
Field-keyed messages, customisable copy, ready to render.
$auth->errors(); // ['password' => 'Password is incorrect!']
Token control
Access + refresh tokens, your secret, your lifetimes.
$auth->tokens(); // ['access' => β¦, 'refresh' => β¦]
One require away
No identity provider, no dashboard, no per-user pricing. Ever.
composer require leafs/authBring your stack
Auth needs PHP, PDO and a users table. Use the Leaf\Auth class anywhere; the extra Leaf niceties light up when Leaf is present.
Then read the full documentation.