devinci-it / shadow-auth
Lightweight file-based PHP authentication library with optional TOTP.
Requires
- php: >=8.1
README
A lightweight, file-based PHP authentication library with optional TOTP 2FA, CSRF protection, and simple processor/form helpers for classic server-rendered apps.
Table of Contents
- Requirements
- Installation
- Quick Start
- Architecture
- Configuration
- Auth Flows
- Facade API
- Publishing Demo, Endpoints, and Wiki
- Serve Demo Locally
- Class Wiki
- Security Notes
- Release and Tagging
- License
Requirements
- PHP
>=8.1 - Composer (for package install and autoload)
Installation
Install through Composer:
composer require devinci-it/shadow-auth
If you are developing this package locally in another app, use a Composer path repository:
{
"repositories": [
{
"type": "path",
"url": "../devinci-it-shadow-auth",
"options": {
"symlink": true
}
}
],
"require": {
"devinci-it/shadow-auth": "*"
}
}
Then update dependencies:
composer update devinci-it/shadow-auth
Quick Start
1. Bootstrap
<?php declare(strict_types=1); require __DIR__ . '/vendor/autoload.php'; use DevinciIT\ShadowAuth\Core\Config; use DevinciIT\ShadowAuth\Facade\Auth; Config::set([ 'storage_path' => __DIR__ . '/storage/shadow.php', 'session_key' => 'shadow_auth_user', 'totp_enabled' => true, 'registration_constraints' => [ 'unique_fields' => ['username', 'email'], 'case_insensitive_fields' => ['username', 'email'], ], ]); Auth::boot();
2. Register
$ok = Auth::registerWithData('alice', 'secure-password', [ 'email' => 'alice@example.com', ]);
3. Login
$result = Auth::beginLogin('alice', 'secure-password'); if ($result === 'authenticated') { // Logged in } if ($result === 'totp_required') { // Show TOTP form and call Auth::verifyPendingTotp($code) }
4. Route Guard
Auth::requireAuth('/views/login.php');
Architecture
Namespace root: DevinciIT\ShadowAuth\
Main components:
Core: business logic managers and config.Facade: static API for app code.Providers: persistence layer (FileUserProvider).Processors: request handlers for login/register/reset/TOTP forms.Services: reusable services (TwoFactorService).Utils: utility helpers (CSRF).View: form builders with CSRF injection.Publisher: file publishing utilities for demo/endpoints/wiki.Shadow\Facade\Auth: compatibility alias facade.
Configuration
Configure with DevinciIT\ShadowAuth\Core\Config::set([...]).
Supported keys:
storage_path(string, required): path to PHP array storage file.session_key(string, optional): auth session key. Default:shadow_auth_user.totp_enabled(bool, optional): global TOTP toggle. Default:true.registration_constraints(array, optional): unique/case-insensitive field rules.
Example:
Config::set([ 'storage_path' => __DIR__ . '/storage/shadow.php', 'totp_enabled' => true, 'registration_constraints' => [ 'unique_fields' => ['username', 'email'], 'case_insensitive_fields' => ['username', 'email'], ], ]);
Auth Flows
Username/password only
Auth::beginLogin($username, $password)- Returns
authenticatedand session is established.
Username/password + TOTP
Auth::beginLogin(...)- Returns
totp_requiredand writes pending state in session. Auth::verifyPendingTotp($code)finalizes login.
Password reset
Auth::requestPasswordResetToken($identifier)returns token (demo mode usage).- Validate before submit with
Auth::hasValidPasswordResetToken($token). - Complete with
Auth::resetPasswordWithToken($token, $newPassword).
Facade API
Available methods in DevinciIT\ShadowAuth\Facade\Auth:
boot(): voidregister(string $username, string $password): boolregisterWithData(string $username, string $password, array $attributes): boolregistrationError(): ?stringattempt(string $username, string $password, ?string $totp = null): boolbeginLogin(string $username, string $password): stringverifyPendingTotp(string $code): boolisTotpPending(): boolpendingUsername(): ?stringcheck(): boolrequireAuth(string $redirectTo = '/views/login.php'): voiduser(): ?arraylogout(): voidsetupTotpSecret(string $username): ?stringconfirmTotp(string $username, string $code): booldisableTotp(string $username): boolenableTotp(): voiddisableTotpGlobally(): voidrequestPasswordResetToken(string $identifier): ?stringhasValidPasswordResetToken(string $token): boolresetPasswordWithToken(string $token, string $newPassword): bool
Publishing Demo, Endpoints, and Wiki
This package includes bin/shadow-auth-publish-demo with multiple modes.
# Full demo scaffold into ./shadow-auth-demo ./vendor/bin/shadow-auth-publish-demo # Overwrite existing files ./vendor/bin/shadow-auth-publish-demo --force # Publish only public assets into host project ./public ./vendor/bin/shadow-auth-publish-demo --public # Publish only views into host project ./views ./vendor/bin/shadow-auth-publish-demo --endpoints # Publish only wiki scaffold into ./shadow-auth-wiki ./vendor/bin/shadow-auth-publish-demo --wiki
Composer script aliases:
composer publish-demo composer publish-demo-force composer publish-endpoints composer publish-endpoints-force
Serve Demo Locally
Use the dedicated helper to create an isolated demo in /tmp, generate a proper composer.json, install dependencies, and run PHP's local server.
./vendor/bin/shadow-auth-serve-demo
Default behavior:
- Creates target directory under
/tmp/shadow-auth-demo-* - Copies
bootstrap.php,src/,public/, andviews/ - Writes
composer.jsonfrom the demo template with local PSR-4 autoload - Runs
composer install(nodevinci-it/shadow-authself-dependency required) - Serves
http://127.0.0.1:8500withphp -S 127.0.0.1:8500 -t public
Useful flags:
./vendor/bin/shadow-auth-serve-demo --target /tmp/shadow-auth-demo --force ./vendor/bin/shadow-auth-serve-demo --port 8600 ./vendor/bin/shadow-auth-serve-demo --no-install
Composer alias:
composer serve-demo
Class Wiki
Detailed per-class documentation is under docs/wiki/.
- Wiki index:
docs/wiki/README.md - Class pages:
docs/wiki/classes/
Security Notes
- Keep storage files outside the public web root where possible.
- Apply restrictive permissions (
0700for directory,0600for file). - Always use HTTPS in production.
- Regenerate session IDs after successful authentication.
- Validate CSRF tokens on all state-changing requests.
- Treat demo password reset tokens as sensitive and short-lived.
Release and Tagging
Create an annotated tag with helper script:
./bin/shadow-auth-tag-release 0.0.3 ./bin/shadow-auth-tag-release 0.0.3 --push
Composer aliases:
composer release-tag -- 0.0.3 composer release-tag-push -- 0.0.3
License
MIT