WebGuard Documentation
Advanced PHP Login and User Management System built on CodeIgniter 4. Secure, extensible, and production-ready with multi-language support, OAuth, 2FA, SSO, REST API, and a full add-on system.
Introduction
Everything you need to know about WebGuard and what it offers.
WebGuard is a complete PHP authentication and user management platform built on top of CodeIgniter 4. It provides a solid, secure foundation so you can focus on building your application instead of re-implementing authentication logic from scratch.
Designed for developers, WebGuard ships with a clean admin panel, REST API, group-based permission system, multi-language support, OAuth/Social login, Two-Factor Authentication, Single Sign-On, a notification engine, and a full add-on/hook system that lets you extend the platform without touching core files.
What's New in v3.0.0
A major release with new features, improvements, and breaking changes.
NEW New Features
- Add-on / Hook system with permission-based visibility
- WhatsApp notification channel
- Storage gateway abstraction layer
- Impersonate user with session restore
- 12 new interface languages (DE, FR, IT, JA, KO, ZH, RU, PL, TR, HI, ID, AR)
- Error pages 400, 403, 404, 503
- SSO token-based authentication
- Module permission control per user group
IMPROVED Improvements
- Redesigned admin UI with modern components
- Notification system with email, SMS, and WhatsApp
- JWT helper rewritten for better token validation
- User group rules now control add-on hook visibility
- Settings panel reorganized with tabs
- Datatable columns now support hook-injected data
- Profile page with Select2 dropdowns
- SweetAlert upgraded to v2 across all views
SECURITY Security Enhancements
- Throttler filter applied to all auth routes
- CSRF token refresh on each request
- Password hashing upgraded to PHP
password_hash() - Demo mode prevents data mutation
- Impersonate flow validates session integrity
- API endpoints secured with JWT expiry checks
BREAKING Breaking Changes
- Minimum PHP version raised to 8.1
- CodeIgniter upgraded to 4.6+
- SweetAlert v1
swal()replaced withSwal.fire() - Add-on hooks without group permission are now hidden by default
- Database migrations must be re-run for new tables
session()->get('token')is now updated on impersonate
Requirements
Server and environment prerequisites before installing WebGuard.
| Component | Minimum | Recommended | Notes |
|---|---|---|---|
| PHP | 8.1 | 8.3 | Extensions: intl, mbstring, json, curl, gd, xml |
| CodeIgniter | 4.6.0 | Latest 4.x | Included in package |
| MySQL | 5.7 | 8.0+ | MariaDB 10.4+ also supported |
| Web Server | Apache / Nginx | Nginx | mod_rewrite required on Apache |
| Composer | 2.x | Latest | Required for dependency management |
Required PHP Extensions
Install on a Standard Server
Deploy WebGuard to a VPS, shared hosting, or cloud server.
upload folder to your server's web root (e.g., /public_html/ or /var/www/html/)..env fileenv to .env and update the following values:
# App CI_ENVIRONMENT = production app.baseURL = 'https://yourdomain.com/' app.appTimezone = 'America/Sao_Paulo' # Database database.default.hostname = localhost database.default.database = your_database database.default.username = your_user database.default.password = your_password database.default.DBDriver = MySQLi # Security encryption.key = hex2bin:YOUR_HEX_KEY_HERE
https://yourdomain.com/install to run the setup wizard, or run migrations via CLI:# 1. Run migrations php spark migrate --all # 2. Run seeds php spark db:seed DataSeeder
| Field | Default Value |
|---|---|
[email protected] | |
| Password | 12345678 |
/install route from app/Config/Routes.php after setup.Install on Localhost (XAMPP / WAMP)
Set up a local development environment for WebGuard.
C:\xampp\htdocs\webguard\ (XAMPP) or C:\wamp\www\webguard\ (WAMP)..env file with your local settings:CI_ENVIRONMENT = development app.baseURL = 'http://localhost/webguard/public/' database.default.hostname = localhost database.default.database = webguard database.default.username = root database.default.password = database.default.DBDriver = MySQLi
/public/ directory. Do not change it to the project root.Install in a Subfolder
Run WebGuard at https://yourdomain.com/app/ instead of the root.
/public_html/app/.baseURL to include the subfolder path:app.baseURL = 'https://yourdomain.com/app/public/'
mod_rewrite is enabled and the .htaccess file inside the public/ directory is present and not blocked.CI4 Native Install
Install WebGuard as a Composer package inside an existing CodeIgniter 4 project.
If you already have a CI4 project and want to integrate WebGuard's auth layer, use the native install method:
# 1. Clone or copy WebGuard files into your project cp -r webguard/app/* your-project/app/ # 2. Install dependencies composer install # 3. Run migrations php spark migrate --all # 4. Run seeds php spark db:seed DataSeeder # 5. Start development server php spark serve
app/Config/Routes.php and app/Config/App.php.Using the REST API
Authenticate and consume WebGuard's built-in REST API from any client.
Authentication
All protected API routes require a Bearer token in the Authorization header. Obtain a token by posting credentials to the login endpoint:
{
"email": "[email protected]",
"password": "your_password"
}
{
"status": "success",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"user": {
"id": 1,
"name": "Admin",
"email": "[email protected]",
"group": "admin"
}
}
Using the Token
curl -X GET https://yourdomain.com/api/users \ -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \ -H "Content-Type: application/json"
Creating REST Endpoints
Add new protected API routes to WebGuard.
app/Controllers/Api/BaseController and use the JwtFilter to protect the route.namespace App\Controllers\Api; use App\Controllers\BaseController; class Products extends BaseController { public function index() { $data = [ ['id' => 1, 'name' => 'Widget', 'price' => 9.99], ]; return $this->response ->setStatusCode(200) ->setJSON(['status' => 'success', 'data' => $data]); } }
$routes->group('api', ['filter' => 'jwt'], function($routes) { $routes->get('products', 'Api\Products::index'); });
Creating CRUD Modules
Use the built-in Maker tool to scaffold a full CRUD module in seconds.
WebGuard includes a Code Maker tool at /tools/maker that generates all the boilerplate for a new CRUD module: migration, model, controller, views, routes, and language keys.
VARCHAR, TEXT, INT, etc.), and whether it's required.php spark migrate.Creating Add-ons
Extend WebGuard without touching core files using the hook system.
WebGuard v3.0.0 features a powerful hook-based add-on system. Add-ons live in app/Modules/ and are registered in app/Modules/Modules.json. They can inject content into predefined hook points throughout the UI and control which user groups can see their hooks.
Add-on File Structure
app/Modules/
└── MyAddon/
├── app.json # Manifest & hook definitions
├── Controllers/
│ └── MyAddon.php
├── Models/
│ └── MyAddonModel.php
├── Views/
│ ├── index.php
│ └── hooks/
│ └── user_list_action.php
└── Database/
└── Migrations/
app.json Manifest
{
"name": "My Addon",
"description": "A sample WebGuard add-on",
"type": "module",
"author": "Your Name",
"homepage": "https://example.com",
"license": "MIT",
"version": "1.0.0",
"requires": {
"webguard": ">=3.0.0"
},
"directory": "MyAddon",
"menu": [
{
"icon": "fas fa-puzzle-piece",
"title": "App.menu_myaddon",
"children": [
{
"title": "App.menu_myaddon_list",
"url": "myaddon",
"external": false
},
{
"title": "App.menu_myaddon_add",
"url": "myaddon/add",
"external": false
}
]
}
],
"hooks": [
{
"point": "user_list_actions",
"actions": [
{
"label": "View Tasks",
"url": "myaddon?user={token}",
"icon": "fas fa-tasks"
}
]
},
{
"point": "settings_tab_nav",
"view": "MyAddon/Views/hooks/settings_tab"
}
]
}
| Field | Required | Description |
|---|---|---|
name | Yes | Display name of the add-on |
description | No | Short description of the add-on |
type | Yes | Must be "module" |
author | No | Author name |
homepage | No | Author or project URL |
license | No | License identifier (e.g. "MIT") |
version | Yes | Semantic version string (e.g. "1.0.0") |
requires.webguard | No | Minimum WebGuard version constraint (e.g. ">=3.0.0") |
directory | Yes | Folder name inside app/Modules/ — alphanumeric + underscore only, cannot be a reserved name |
menu | Yes | Array of sidebar menu entries injected under the Modules divider |
hooks | No | Array of hook definitions (view or actions mode) |
menu[] fields
| Field | Required | Description |
|---|---|---|
icon | Yes | FontAwesome class (e.g. "fas fa-puzzle-piece") |
title | Yes | Translation key (e.g. "App.menu_myaddon") |
children | Yes* | Submenu items — if present, url/external are not needed on the parent |
url | Yes* | Route URL — only when there are no children |
external | Yes* | true opens in a new tab — only when there are no children |
menu[].children[] fields
| Field | Required | Description |
|---|---|---|
title | Yes | Translation key |
url | Yes | Route URL (relative to site root) |
external | Yes | true opens in a new tab; false uses site_url() |
Permission-based Hook Visibility
In v3.0.0, hooks are only shown to users whose group is listed in the add-on's rules array in Modules.json. An empty rules array means no one sees the hooks.
[
{
"name": "My Addon",
"directory": "MyAddon",
"status": true,
"rules": ["115b5ad39b853084209caf6824224f6b"]
}
]
rules array contains group tokens (not group names). Find the token in Settings → Groups or directly in the user_group table. You can also add "permission" to individual hooks for finer-grained control.Available Hook Points
| Hook Point | Location | Mode |
|---|---|---|
user_list_actions | User list dropdown per row | actions / view |
user_list_columns_header | User list table header | actions (tag: th) |
user_list_columns_data | User list table row data | view |
user_form_extra_fields | User add/edit form | view |
user_form_actions | User form action buttons | actions |
settings_tab_nav | Settings page tab navigation | view |
settings_tab_content | Settings page tab content | view |
notification_form_extra | Notification form extra fields | view |
Creating Languages
Add a new interface language to WebGuard.
app/Language/en/ and rename it to your language code (e.g., de for German).App.phpapp/Language/de/App.php and translate all values. Keep the array keys unchanged.app/Views/themes/backend/focus2/layout/main.php and in app/Views/themes/backend/focus2/form/profile/index.php.Two-Factor Authentication (2FA)
Enable TOTP-based 2FA for admin and user accounts.
OAuth / Social Login
Allow users to sign in with Google, Facebook, GitHub, and other providers.
https://yourdomain.com/sso/callback/PROVIDER.Client ID and Client Secret, and enable it.| Provider | Callback URL | Status |
|---|---|---|
/sso/callback/google | Supported | |
/sso/callback/facebook | Supported | |
| GitHub | /sso/callback/github | Supported |
| Microsoft | /sso/callback/microsoft | Supported |
/sso/callback/linkedin | Supported |
Single Sign-On (SSO)
Authenticate users from an external system via token handoff.
WebGuard implements a broker-based SSO model. WebGuard acts as the SSO Server (identity provider). External applications act as Brokers — they delegate authentication to WebGuard via a shared secret key, without ever handling user passwords directly.
Broker Flow (step by step)
token (random string), computes a checksum, and redirects the user's browser to:
GET /sso/attach?broker=MY_BROKER&token=TOKEN&checksum=HMAC&return_url=https://myapp.com/after-attach
WebGuard links the broker's token to a server-side session and redirects back to
return_url.
GET /sso/verify — with header Authorization: SSO-Broker MY_BROKER:TOKEN
WebGuard returns the user object (200) if a session exists, or 204 No Content if no one is logged in yet.
POST /sso/login — body: [email protected]&password=secret
Header:
Authorization: SSO-Broker MY_BROKER:TOKEN
On success WebGuard returns the user profile (200). The session is now shared — any other broker using the same SSO server will see this user as logged in via
/sso/verify.
GET /sso/token — Header: Authorization: SSO-Broker MY_BROKER:TOKEN
Returns
{ "token": "eyJ...", "expires_in": 3600 }. Use this JWT to authenticate calls to WebGuard's REST API or other services.
POST /sso/logout — Header: Authorization: SSO-Broker MY_BROKER:TOKEN
Destroys the SSO session. All brokers sharing that session will immediately see the user as logged out on the next
/sso/verify call.
Endpoints Reference
| Method | Endpoint | Auth Header | Description |
|---|---|---|---|
| GET | /sso/attach | — | Link broker token to SSO session (browser redirect) |
| GET | /sso/verify | SSO-Broker | Returns logged-in user (200) or 204 if not authenticated |
| POST | /sso/login | SSO-Broker | Authenticate user with email + password |
| POST | /sso/logout | SSO-Broker | Destroy SSO session |
| GET | /sso/userInfo | SSO-Broker | Alias for /sso/verify |
| GET | /sso/token | SSO-Broker | Issue a short-lived JWT for the authenticated user |
Authorization Header Format
Authorization: SSO-Broker MY_BROKER:TOKEN
Checksum Calculation (attach)
The checksum sent to /sso/attach must be computed as:
$checksum = hash_hmac('sha256', 'attach' . $token, $secretKey . $broker);
User Profile Payload
Returned by /sso/verify, /sso/login, and /sso/userInfo:
{
"token": "abc123...",
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"picture": "https://...",
"language": "en",
"country": "US",
"status": 1,
"group": "115b5ad39b853084209caf6824224f6b"
}
JWT Token Response
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 3600
}
- The
brokeridentifier must be alphanumeric (max 64 chars). Thetokenmust be 8–128 alphanumeric chars. - All SSO endpoints return
503if SSO is disabled in settings. - Blocked or inactive users are rejected at login.
- The JWT lifetime is configured via Settings → SSO → Token Lifetime (default: 3600 s).
Notifications
Send notifications via Email, SMS, and WhatsApp (new in v3.0.0).
WebGuard's notification engine allows sending templated messages to users across multiple channels. Templates are managed at Settings → Templates.
| Channel | Configuration | v3.0.0 |
|---|---|---|
| Email (SMTP) | Settings → Email | Available |
| SMS (Twilio / SMPP) | Settings → SMS | Available |
| Settings → WhatsApp | NEW | |
| In-app | Built-in | Available |
Sending a Notification Programmatically
$notif = new \App\Models\NotificationModel(); $notif->send([ 'recipient' => $userToken, 'template' => 'welcome', 'channel' => ['email', 'whatsapp'], 'data' => ['name' => $user['first_name']], ]);
Permissions & User Groups
Control what each user group can access throughout the application.
WebGuard uses a group-based permission system. Each user belongs to a group, and each group has a set of allowed controller actions stored as JSON in the user_group table's rules column.
Permission Structure
{
"User": ["index", "add", "edit", "store", "delete", "impersonate"],
"Settings": ["index", "store", "oauth", "module"],
"Activity": ["index"]
}
Each key is a controller name and each value is an array of allowed method names. The menu and UI elements are automatically hidden for methods the user's group does not have access to.
"permission": "Task" in app.json will only be visible to groups that have Task in their rules.API Reference
Complete list of available REST API endpoints.
Authentication
Users
Groups
Profile
Notifications
/api/auth/login require a valid Bearer token in the Authorization header.Configuration Reference
Key environment variables and configuration options.
| Key | Default | Description |
|---|---|---|
CI_ENVIRONMENT | production | Set to development to show errors |
app.baseURL | — | Full URL including trailing slash |
app.appTimezone | UTC | PHP timezone for dates |
demo.mode | false | Prevent data mutation in demo |
theme.backend.path | themes/backend/focus2/ | Active backend theme path |
jwt.secret | — | Secret key for JWT signing |
jwt.ttl | 3600 | Token TTL in seconds |
Changelog
Release history for WebGuard.
- Add-on / Hook system with group-based permission control
- WhatsApp notification channel
- Storage gateway abstraction layer
- Impersonate user with full session restore (including token)
- 12 new interface languages
- Custom error pages: 400, 403, 404, 503
- SSO token-based authentication flow
- Module permission management per user group
- Redesigned admin UI with modern components
- JWT helper rewritten with better token validation
- SweetAlert upgraded to v2 across all views
- Profile page Select2 dropdowns now load correctly
- Datatable columns support hook-injected data
- Throttler filter on all auth routes
- Demo mode prevents data mutation
- PHP 8.1+ required (raised from 7.4)
- CodeIgniter upgraded to 4.6+
- Add-on hooks hidden by default when
rulesis empty
- REST API with JWT authentication
- Two-Factor Authentication (TOTP)
- OAuth social login (Google, Facebook, GitHub)
- Code Maker tool for CRUD scaffolding
- Menu editor with drag-and-drop
- Group permissions now stored as JSON rules
- Notification system with email and SMS
- CSRF protection on all forms
- Fixed session fixation vulnerability on login
- Multi-language support (EN, PT, ES)
- Dark mode toggle
- Improved responsive layout for mobile
- Password reset token expiry now enforced
- Initial release on CodeCanyon
- Login, registration, password recovery
- User management with group permissions
- Activity log
- Profile with avatar upload
- Built on CodeIgniter 4
Support
Get help with WebGuard installation, customization, and bugs.