CodeIgniter 4 Shield — Auth Reference
Shield is the official authentication and authorization library for CodeIgniter 4. It is not Laravel Sanctum, Passport, or Breeze. Do not apply Laravel auth patterns here.
Related skills: ci4 for core framework patterns, ci4-api for REST API patterns.
Reference Documents
For deep dives, read the relevant reference from references/:
| Reference |
When to read |
references/configuration.md |
Auth.php, AuthGroups.php, password validators, views, authenticators |
references/session-auth.md |
Login/logout flow, remember me, web authentication |
references/token-auth.md |
Access tokens, HMAC tokens, JWT — generation, revocation, scopes |
references/groups-permissions.md |
Groups, permissions, matrix, direct user permissions, wildcards |
references/user-model.md |
User entity, UserModel, extending, creating/finding/updating users |
references/filters.md |
All Shield filters, route protection, filter arguments |
references/actions.md |
Email activation, Email 2FA, magic links, password handling, banning |
references/events-customization.md |
Events, custom views, extending controllers, routes, testing |
Installation & Setup
composer require codeigniter4/shield
php spark shield:setup # publishes Config files + migrations
php spark migrate # creates Shield's database tables
Database Tables
| Table |
Purpose |
users |
Core user data (username, active, last_active) |
auth_identities |
All credential types (email/password, access tokens, HMAC keys) |
auth_logins |
Login attempt log (success + failure) |
auth_remember_tokens |
Remember-me tokens |
auth_groups_users |
User-to-group pivot |
auth_permissions_users |
User-to-permission pivot |
Auth Helper — Core Functions
The auth() helper is globally available. No manual loading needed.
auth()->loggedIn(); // bool — is someone logged in?
auth()->user(); // User entity or null
auth()->id(); // int user ID or null
// Specify authenticator
auth('session')->loggedIn();
auth('tokens')->user();
// Attempt login
$result = auth()->attempt([
'email' => $email,
'password' => $password,
]);
if ($result->isOK()) { /* success */ }
// $result->reason() — error message on failure
// Logout
auth()->logout();
// Check credentials without logging in
$result = auth()->check(['email' => $email, 'password' => $password]);
GOTCHA: attempt() returns a Result object, not a boolean. Always check $result->isOK().
Groups & Permissions (Quick Reference)
See references/groups-permissions.md for complete reference.
$user = auth()->user();
// Groups
$user->addGroup('admin');
$user->removeGroup('admin');
$user->inGroup('admin'); // bool
$user->inGroup('admin', 'superadmin'); // true if in ANY
$user->getGroups(); // ['admin', 'developer']
// Permissions
$user->can('posts.create'); // bool (via group matrix OR direct)
$user->cannot('users.delete'); // bool
$user->addPermission('admin.access'); // direct permission
$user->removePermission('admin.access');
Groups and permissions are defined in app/Config/AuthGroups.php.
Filters (Quick Reference)
See references/filters.md for complete reference. Shield auto-registers these — no manual registration needed.
| Filter |
Purpose |
session |
Requires session auth |
tokens |
Requires Bearer token auth |
hmac |
Requires HMAC token auth |
jwt |
Requires JWT auth |
chain |
Tries session, then tokens (SPA + mobile) |
group |
Checks group membership |
permission |
Checks permission |
force-reset |
Checks if password reset required |
auth-rates |
Rate limiting for auth routes |
// Route protection
$routes->get('dashboard', 'DashboardController::index', ['filter' => 'session']);
$routes->get('admin', 'AdminController::index', ['filter' => ['session', 'group:admin,superadmin']]);
$routes->get('api/me', 'Api\UserController::me', ['filter' => 'tokens']);
User Entity (Quick Reference)
See references/user-model.md for complete reference.
$user = auth()->user();
$user->getEmail(); // email address
$user->username; // username
$user->password = 'new-pass'; // auto-hashed via setter
$user->isBanned(); // bool
$user->ban('Reason'); // ban user
$user->unBan(); // remove ban
$user->isActivated(); // bool
$user->activate(); // manual activation
$user->forcePasswordReset(); // require change on next login
// Access tokens
$token = $user->generateAccessToken('name');
$user->revokeAccessToken($tokenId);
Configuration (Quick Reference)
See references/configuration.md for complete reference.
// app/Config/Auth.php — key settings
public array $redirects = ['register' => '/', 'login' => '/', 'logout' => 'login'];
public array $actions = [
'register' => null, // EmailActivator::class for email verification
'login' => null, // Email2FA::class for two-factor auth
];
public array $validFields = ['email']; // add 'username' for username login
public string $defaultAuthenticator = 'session';
// app/Config/AuthGroups.php — groups + permissions
public array $groups = ['superadmin' => [...], 'admin' => [...], 'user' => [...]];
public string $defaultGroup = 'user';
public array $permissions = ['admin.access' => '...', 'users.create' => '...'];
public array $matrix = ['superadmin' => ['admin.*', 'users.*'], 'admin' => ['admin.access']];
Key Gotchas
See references/events-customization.md for the complete list.
attempt() returns a Result, not bool — always use $result->isOK()
raw_token only available once — capture at generation, hashed before storage
- Filter order matters —
session must run before group (auth before authz)
- Parent route group filters don't merge into children — declare on each group
- Custom UserModel must be registered in
Auth.php's $userProvider
- Password auto-hashed by entity setter — never manually hash before setting
- Credentials live in
auth_identities — not the users table
- Email config required for activation, 2FA, and magic links
$validFields controls login fields — add 'username' to allow username login
chain filter is for dual-client endpoints — don't use when auth type is known
1---2name: ci4-shield3description: Comprehensive CodeIgniter 4 Shield authentication and authorization skill. Use when working with Shield auth — session login, access tokens, HMAC tokens, JWT, groups, permissions, user model/entity, filters, email activation, two-factor auth, magic links, banning, force password reset, or customizing auth views/controllers. Activates on mentions of "Shield", "auth()", "loggedIn", "groups", "permissions", "access token", "HMAC", "JWT", "Email2FA", "EmailActivator", "magic link", "Shield filter", or any Shield-specific pattern in a CI4 context.4---56# CodeIgniter 4 Shield — Auth Reference78Shield is the **official** authentication and authorization library for CodeIgniter 4. It is **not Laravel Sanctum, Passport, or Breeze**. Do not apply Laravel auth patterns here.910> **Related skills**: `ci4` for core framework patterns, `ci4-api` for REST API patterns.1112## Reference Documents1314For deep dives, read the relevant reference from `references/`:1516| Reference | When to read |17|---|---|18| `references/configuration.md` | Auth.php, AuthGroups.php, password validators, views, authenticators |19| `references/session-auth.md` | Login/logout flow, remember me, web authentication |20| `references/token-auth.md` | Access tokens, HMAC tokens, JWT — generation, revocation, scopes |21| `references/groups-permissions.md` | Groups, permissions, matrix, direct user permissions, wildcards |22| `references/user-model.md` | User entity, UserModel, extending, creating/finding/updating users |23| `references/filters.md` | All Shield filters, route protection, filter arguments |24| `references/actions.md` | Email activation, Email 2FA, magic links, password handling, banning |25| `references/events-customization.md` | Events, custom views, extending controllers, routes, testing |2627---2829## Installation & Setup3031```bash32composer require codeigniter4/shield33php spark shield:setup # publishes Config files + migrations34php spark migrate # creates Shield's database tables35```3637### Database Tables3839| Table | Purpose |40|---|---|41| `users` | Core user data (username, active, last_active) |42| `auth_identities` | All credential types (email/password, access tokens, HMAC keys) |43| `auth_logins` | Login attempt log (success + failure) |44| `auth_remember_tokens` | Remember-me tokens |45| `auth_groups_users` | User-to-group pivot |46| `auth_permissions_users` | User-to-permission pivot |4748---4950## Auth Helper — Core Functions5152The `auth()` helper is globally available. No manual loading needed.5354```php55auth()->loggedIn(); // bool — is someone logged in?56auth()->user(); // User entity or null57auth()->id(); // int user ID or null5859// Specify authenticator60auth('session')->loggedIn();61auth('tokens')->user();6263// Attempt login64$result = auth()->attempt([65 'email' => $email,66 'password' => $password,67]);68if ($result->isOK()) { /* success */ }69// $result->reason() — error message on failure7071// Logout72auth()->logout();7374// Check credentials without logging in75$result = auth()->check(['email' => $email, 'password' => $password]);76```7778**GOTCHA**: `attempt()` returns a `Result` object, not a boolean. Always check `$result->isOK()`.7980---8182## Groups & Permissions (Quick Reference)8384See `references/groups-permissions.md` for complete reference.8586```php87$user = auth()->user();8889// Groups90$user->addGroup('admin');91$user->removeGroup('admin');92$user->inGroup('admin'); // bool93$user->inGroup('admin', 'superadmin'); // true if in ANY94$user->getGroups(); // ['admin', 'developer']9596// Permissions97$user->can('posts.create'); // bool (via group matrix OR direct)98$user->cannot('users.delete'); // bool99$user->addPermission('admin.access'); // direct permission100$user->removePermission('admin.access');101```102103Groups and permissions are defined in `app/Config/AuthGroups.php`.104105---106107## Filters (Quick Reference)108109See `references/filters.md` for complete reference. Shield auto-registers these — no manual registration needed.110111| Filter | Purpose |112|---|---|113| `session` | Requires session auth |114| `tokens` | Requires Bearer token auth |115| `hmac` | Requires HMAC token auth |116| `jwt` | Requires JWT auth |117| `chain` | Tries session, then tokens (SPA + mobile) |118| `group` | Checks group membership |119| `permission` | Checks permission |120| `force-reset` | Checks if password reset required |121| `auth-rates` | Rate limiting for auth routes |122123```php124// Route protection125$routes->get('dashboard', 'DashboardController::index', ['filter' => 'session']);126$routes->get('admin', 'AdminController::index', ['filter' => ['session', 'group:admin,superadmin']]);127$routes->get('api/me', 'Api\UserController::me', ['filter' => 'tokens']);128```129130---131132## User Entity (Quick Reference)133134See `references/user-model.md` for complete reference.135136```php137$user = auth()->user();138139$user->getEmail(); // email address140$user->username; // username141$user->password = 'new-pass'; // auto-hashed via setter142143$user->isBanned(); // bool144$user->ban('Reason'); // ban user145$user->unBan(); // remove ban146147$user->isActivated(); // bool148$user->activate(); // manual activation149150$user->forcePasswordReset(); // require change on next login151152// Access tokens153$token = $user->generateAccessToken('name');154$user->revokeAccessToken($tokenId);155```156157---158159## Configuration (Quick Reference)160161See `references/configuration.md` for complete reference.162163```php164// app/Config/Auth.php — key settings165public array $redirects = ['register' => '/', 'login' => '/', 'logout' => 'login'];166public array $actions = [167 'register' => null, // EmailActivator::class for email verification168 'login' => null, // Email2FA::class for two-factor auth169];170public array $validFields = ['email']; // add 'username' for username login171public string $defaultAuthenticator = 'session';172```173174```php175// app/Config/AuthGroups.php — groups + permissions176public array $groups = ['superadmin' => [...], 'admin' => [...], 'user' => [...]];177public string $defaultGroup = 'user';178public array $permissions = ['admin.access' => '...', 'users.create' => '...'];179public array $matrix = ['superadmin' => ['admin.*', 'users.*'], 'admin' => ['admin.access']];180```181182---183184## Key Gotchas185186See `references/events-customization.md` for the complete list.1871881. **`attempt()` returns a `Result`, not bool** — always use `$result->isOK()`1892. **`raw_token` only available once** — capture at generation, hashed before storage1903. **Filter order matters** — `session` must run before `group` (auth before authz)1914. **Parent route group filters don't merge into children** — declare on each group1925. **Custom UserModel must be registered** in `Auth.php`'s `$userProvider`1936. **Password auto-hashed by entity setter** — never manually hash before setting1947. **Credentials live in `auth_identities`** — not the `users` table1958. **Email config required** for activation, 2FA, and magic links1969. **`$validFields` controls login fields** — add `'username'` to allow username login19710. **`chain` filter is for dual-client endpoints** — don't use when auth type is known