Modern Auth Lab is a progressive security project for exploring modern web authentication with PHP, vanilla JavaScript, TOTP, Passkeys/WebAuthn, controlled MFA fallback strategies, tests, coverage, mutation testing, and CI/CD.
The project is intentionally built step by step. It starts with a small framework-free foundation before adding authentication behavior.
Implemented foundation:
- Agent development rules.
- Project roadmap and security documentation.
- PHP 8.5 backend tooling with Composer.
- PHPUnit, PHPStan, and PHP CS Fixer.
- Vite frontend tooling with vanilla JavaScript.
- Vitest, V8 coverage, ESLint, and Prettier.
- Minimal PHP HTTP foundation with
public/as the web root. GET /healthdiagnostic route.- Server-side session primitives and explicit authentication session states.
- CSRF token primitives for future session-backed forms and unsafe requests.
- SQLite persistence foundation with migration tracking.
- User persistence schema, repository, password hashing, and password verification workflow.
- Minimal password login form with CSRF validation.
- Password-only full session login for the current pre-MFA milestone.
- Protected
/accountroute. - CSRF-protected logout.
- Initial session-backed login rate limiting.
- SQLite-backed basic security events.
- Authenticator-app TOTP enrollment with QR code setup.
- Password + TOTP login flow for users with active TOTP.
- TOTP challenge anti-replay protection.
- TOTP challenge rate limiting.
- TOTP challenge security events.
- Pending TOTP enrollment expiration.
- Account security page for TOTP lifecycle status.
- Normal TOTP disable with current authenticator code.
- TOTP recovery-code generation, hash-only storage, one-time display, and service-level verification.
- Passkey/WebAuthn foundation primitives.
- Passkey credential persistence.
- Passkey enrollment and authentication challenge generation.
- Passkey enrollment browser module.
- Server-side Passkey enrollment attestation verification boundary.
- Session-tracked pending MFA method for explicit server-side routing between TOTP and Passkey.
- HTTP-wired Passkey enrollment: challenge endpoint, verification endpoint, account security UI, and browser wiring.
- Server-side Passkey authentication assertion verification behind a project-owned boundary.
- Password + Passkey login flow with Passkey preferred over TOTP when both are active.
- Individual Passkey revocation with per-credential CSRF protection.
- Passkey-specific security events for enrollment, authentication, and revocation.
Not implemented yet:
- CSRF middleware.
- Controlled TOTP fallback when Passkey authentication is unavailable.
- Trusted devices.
- Login recovery with recovery-code submission.
- User-facing SQLite/libSQL persistence features.
- CI/CD.
- PHP 8.5+
- Composer 2+
- Node.js 22+
- npm 10+
- SQLite PDO extension
The application reads local runtime configuration from .env.local when the file exists. The repository commits .env.example as the safe template.
Required local variables:
TOTP_SECRET_ENCRYPTION_KEY=
TOTP_RATE_LIMIT_MAX_ATTEMPTS=5
TOTP_RATE_LIMIT_LOCK_SECONDS=300
WEBAUTHN_RP_ID=127.0.0.1
WEBAUTHN_RP_NAME="Modern Auth Lab"
WEBAUTHN_ALLOWED_ORIGINS=http://127.0.0.1:8080
WEBAUTHN_CHALLENGE_TTL_SECONDS=300
WEBAUTHN_TIMEOUT_MS=60000
WEBAUTHN_USER_VERIFICATION=preferredTOTP_SECRET_ENCRYPTION_KEY must contain a Base64-encoded 32-byte key used to encrypt TOTP secrets before SQLite persistence.
Generate a local key:
php -r 'echo "TOTP_SECRET_ENCRYPTION_KEY=", base64_encode(random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES)), PHP_EOL;'The rate-limit variables control the TOTP challenge brute-force protection:
TOTP_RATE_LIMIT_MAX_ATTEMPTS: failed TOTP submissions before temporary lockout.TOTP_RATE_LIMIT_LOCK_SECONDS: lockout duration in seconds.
The WebAuthn variables define the local relying-party configuration used for Passkey enrollment and verification primitives:
WEBAUTHN_RP_ID: relying-party id, usually the effective host.WEBAUTHN_RP_NAME: user-facing service name shown by authenticators.WEBAUTHN_ALLOWED_ORIGINS: comma-separated origins accepted by server-side verification.WEBAUTHN_CHALLENGE_TTL_SECONDS: lifetime of generated WebAuthn challenges.WEBAUTHN_TIMEOUT_MS: browser ceremony timeout hint.WEBAUTHN_USER_VERIFICATION:required,preferred, ordiscouraged.
Install backend dependencies:
composer installInstall frontend dependencies:
npm installStart the PHP development server:
composer serveThe serve script disables Composer's default process timeout so the local
server can stay open during manual demos.
Health check:
curl http://127.0.0.1:8080/healthRun backend checks:
composer test
composer analyse
composer cs:checkCreate a local development user:
composer seed:dev-userDevelopment credentials:
Email: dev@example.com
Password: DevPassword123!
Login page:
http://127.0.0.1:8080/login
Protected account page:
http://127.0.0.1:8080/account
Account security page:
http://127.0.0.1:8080/account/security
Start the Vite development server:
npm run devRun frontend checks:
npm run build
npm test
npm run coverage
npm run lint
npm run formatassets/ Frontend JavaScript and CSS
docs/ Roadmap, security notes, architecture notes, and decisions
public/ Public web root
src/ PHP application source
tests/ Backend and frontend tests
The project uses a layered architecture (Domain / Application / Infrastructure / Http) to make security boundaries visible: what is trusted server-side, what comes from the browser, where authentication decisions live, and where persistence starts.
This structure is intentionally more explicit than a typical CRUD application. The goal is pedagogical clarity for a security lab, not framework mimicry. Every layer has a single responsibility, so authentication state, MFA challenges, and credential storage remain easy to audit.
Security-sensitive decisions must remain server-side. Frontend code may improve user experience, but it must not decide authentication, authorization, MFA fallback eligibility, recovery state, or trusted-device policy.
Authentication will be modeled as explicit states. Partial authentication must not be treated as a full authenticated session.
Start with:
- Roadmap
- Architecture
- Security model
- Authentication flows
- Fallback strategy
- Security concepts
- TOTP concept note
- Passkeys and WebAuthn concept note
- v0.5.0 TOTP foundation implementation notes
- v0.6.0 Password + TOTP flow implementation notes
- v0.7.0 TOTP lifecycle and recovery implementation notes
- v0.8.0 Passkey / WebAuthn foundation implementation notes
- v0.9.0 Password + Passkey flow implementation notes
- Decision records
main represents the latest project version. Stable milestones are preserved with Git tags and GitHub releases.