Auth & Middleware

Last updated: 04/17/2026 · Written by Agent0

Auth & Middleware

StackCTL includes a built-in authentication system and a set of route middleware that handles the most common access control scenarios out of the box. Middleware is applied directly in your route definitions — no separate configuration files needed.


Built-in Middleware

The following middleware is registered automatically and is available on any route without any setup.

auth — Require login

Redirects unauthenticated users to /login. Use this on any route that requires the user to be signed in.

$router->get('/dashboard', 'DashboardController@index')
       ->middleware('auth');

guest — Require no login

Redirects already-authenticated users to /dashboard. Use this on login and registration pages so logged-in users don't see them.

$router->get('/login', 'AuthController@login')
       ->middleware('guest');

role — Require a specific role

Checks that the authenticated user's role matches. Aborts with a 403 Forbidden if it doesn't. Pass multiple roles separated by commas — the user must have any one of them.

// Single role
$router->get('/admin', 'AdminController@index')
       ->middleware('role:admin');

// Any of multiple roles
$router->get('/reports', 'ReportsController@index')
       ->middleware('role:admin,developer,editor');

can — Require a permission

Checks the user against the permissions map defined in config/auth.php. Aborts with 403 if the check fails. Takes an action and a resource as parameters.

$router->get('/articles/approve/{id}', 'ArticlesController@approve')
       ->middleware('can:approve,article');

Define the permission map in config/auth.php:

'permissions' => [
    'edit'     => ['article' => ['admin', 'editor']],
    'approve'  => ['article' => ['admin']],
    'delete'   => ['article' => ['admin']],
],

Route Groups

Apply middleware to multiple routes at once by wrapping them in a group. All routes inside the group inherit the group's middleware — no need to repeat it on every route.

// All routes in this group require login
$router->group(['middleware' => 'auth'], function ($router) {
    $router->get('/dashboard', 'DashboardController@index');
    $router->get('/profile',   'ProfileController@index');
    $router->post('/profile',  'ProfileController@update');
});

// Prefix + middleware together
$router->group(['prefix' => '/admin', 'middleware' => 'role:admin'], function ($router) {
    $router->get('/users',    'AdminController@users');    // → /admin/users
    $router->get('/settings', 'AdminController@settings'); // → /admin/settings
});

Nested groups

Groups can be nested. Middleware stacks from the outside in — both layers apply to the innermost routes.

$router->group(['middleware' => 'auth'], function ($router) {
    $router->group(['middleware' => 'role:admin'], function ($router) {
        $router->get('/admin', 'AdminController@index');
        // Requires: logged in AND role is admin
    });
});

Custom Middleware

For anything project-specific, use $router->define() to register a custom middleware by name. Define it once in routes/web.php and use it just like the built-ins.

// Define the middleware
$router->define('subscribed', function () {
    if (!user('is_subscribed')) {
        redirect('/upgrade');
    }
});

// Apply it to routes
$router->get('/premium', 'PremiumController@index')
       ->middleware('subscribed');

Auth Helpers

Beyond route protection, StackCTL provides a set of global helpers for checking auth state anywhere in your controllers or views.

is_auth()

Returns true if the current user is logged in.

if (is_auth()) {
    // user is logged in
}

auth()

Returns the current user's session data. Pass a field name to get a specific value.

auth()          // full session array
auth('name')    // display name
auth('email')   // email address
auth('role')    // role string

user()

Returns the current user's full database record. Only runs one query per request regardless of how many times it's called — the result is cached statically.

user()              // full database record
user('email')       // specific field
user('is_subscribed') // any column from the users table

Use auth() for quick access to session-stored values (name, email, role). Use user() when you need accurate, up-to-date data directly from the database.

has_role()

Check if the current user has a specific role. Pass a string for one role or an array to check if the user has any of the listed roles.

has_role('admin')
has_role(['admin', 'developer'])

can()

Check a permission directly in a controller or view — the same check the can: middleware runs.

if (can('edit', 'article')) {
    // show edit button
}

// In a view:
<?php if (can('delete', 'article')): ?>
    <button>Delete</button>
<?php endif; ?>

Auth Configuration

The authentication system has several options you can toggle in config/auth.php:

  • allow_registration — Enable or disable public user registration
  • verify_email — Require email verification after registration
  • remember_me — Enable "Remember Me" persistent login via a secure cookie
  • mfa_enabled — Enable multi-factor authentication (email code or authenticator app)
  • permissions — Define the action/resource/role map used by can() and can: middleware
Was this helpful?