Open source Zero dependencies MIT license PHP 8.0+ Self-hosted

A hardened, zero-dependency PHP login system.

A production-ready, fully self-hosted starter kit for building online service platforms in plain, readable PHP. Zero external dependencies. Minimal attack surface. Maximal features & scalability.

Layered authentication shield with a keyhole at its centre, ringed by concentric defense layers.

Everything SaaS needs, built-in.

No add-ons to install, no services to wire up. It all ships in the repo.

01Accounts & sign-in
  • Login & registration
    • Email verification & activation
    • First-party image CAPTCHA
    • Inactivity auto-logout
  • Email password reset
    • Selector / validator tokens
  • Remember-me
    • Rotating, hardened cookies
  • Editable user profiles
02Integration & identity
  • OAuth2 single sign-on
    • Discord, GitHub, Google, Microsoft
    • Add a provider in one array entry
  • REST authentication API
    • Bearer tokens with refresh rotation
  • GDPR compliance tools
    • Account data export
    • Account soft-delete
03Roles & administration
  • Permission system
    • Multi-level access gating
    • User administration dashboard
  • Developer console
    • Maintenance mode
    • Feature & security toggles
    • Global settings
    • Scheduled task runner
    • Automatic database backups
    • DNS integrity monitor
  • Global error & status messaging
04Analytics & insight
  • First-party analytics suite
    • Analytics dashboard
    • Client fingerprinting
    • Session replay & heatmaps
  • Custom link tracking
    • Create unique links for unique uses / posts
    • Tracks per-day & cumulative link analytics
    • Custom link codes
05Security by default
  • Site-wide defenses
    • Parameterized SQL everywhere
    • CSRF tokens on every mutation
    • Header & email-injection guards
    • Brute-force & enumeration defense
    • Argon2id password hashing
06Footprint
  • Requirements
    • PHP 8.0+
    • MySQL or MariaDB
    • Apache-compatible host
    • Shared-hosting friendly
  • Nothing to install
    • No Composer, no npm
    • No CDN — origin-served assets
    • One pinned library (PHPMailer)

The threat ledger.

Attack classes this codebase defends against, the countermeasure for each, and the file where it lives.

Attack classes and their implemented defenses
#Attack classDefense as implementedWhere
01SQL injectionPrepared statements on every query that carries user input; no string-built SQL, no blocklist filters.*/includes/*.inc.php
02Cross-site scriptingOutput encoding via e() at render time; admin panel renders exclusively through DOM APIs.security_functions.php, dashboard.js
03Cross-site request forgeryPer-session synchronizer tokens on every state change, verified with hash_equals, backed by SameSite cookies.security_functions.php
04Credential brute forcePer-account throttling inside a rolling window, plus a CSPRNG-answered CAPTCHA gating registration.login.inc.php, SecureCaptcha.php
05User enumerationA dummy hash is verified when the account is unknown, keeping response timing and messages uniform.login.inc.php
06Session fixation & hijackStrict session mode, id regeneration on privilege change, HttpOnly / Secure / SameSite cookie flags.secure_session_start()
07Remember-me token theftSelector/validator pairs hashed with SHA-256, rotated on each use; reuse of a stale validator revokes the whole family.auth_functions.php
08Offline password crackingArgon2id hashing with a bcrypt fallback and a minimum-length policy; oversized inputs are rejected before hashing.hash_password()
09Reset / verification token forgery256-bit random tokens stored as SHA-256 digests, single-use, one-hour expiry, constant-time comparison.sendtoken.inc.php, verify.inc.php
10Privilege escalation & IDORAccess levels enforced inside the SQL of every admin action; no request may grant a level above its caller's.dashboard/includes/api.inc.php
11Malicious file uploadReal MIME detection via finfo against an allow-list, random hex filenames, and a storage directory that refuses to execute scripts.profile-edit.inc.php, uploads/.htaccess
12OAuth login CSRFCryptographically random single-use state bound to provider and intent, checked in constant time; PKCE where supported; unverified provider emails refused.login/index.php, oauth.php
13OAuth account pre-hijackingIdentities matched on provider user id, never on email address, so a matching email cannot inherit an existing account. Server-side SSRF allow-list on every provider call.oauth.php
14Verification-token session confusionRedeeming a token elevates the session only when the token's email matches the signed-in user, compared in constant time.verify.inc.php
15Supply-chain compromiseNo registry installs and no CDN loads exist to poison; the one vendored library updates only by reviewed commit; CSP forbids off-origin script.repository root
16Clickjacking & MIME confusionFrame-ancestors restricted to same origin, nosniff on every response, content types declared explicitly.send_security_headers()
17Information disclosureGeneric error pages, display_errors off, secrets stored above the document root, include-only paths answered with 404.error.php, .htaccess, phprc

Before you commit

Questions worth asking.

Whether you're weighing this against a framework, a CMS, or a hosted identity service, here's what usually decides it.

Why run this instead of a framework's built-in auth?

Framework auth — Django's auth, a Laravel starter kit, Passport in Node — assumes you've already adopted the framework, its ORM, its middleware, and its dependency tree. This is the account layer without that commitment: it drops onto any PHP host, owns only the tables it needs, and leaves the rest of your stack alone. You read the whole thing in an afternoon instead of tracing behavior through a vendor directory you'll never fully audit.

We're on WordPress for the logins. Why move off it?

WordPress carries an entire CMS, theme layer, and plugin ecosystem to give you user accounts, and each plugin is a maintainer you're trusting and a patch cadence you're chasing. If accounts are all you actually need, this replaces that surface with a fixed, readable codebase that has no plugin auto-updates, no unknown third-party code, and no admin surface you didn't write. Fewer moving parts is fewer things that break at 3am.

What does "zero dependencies" actually buy me?

Package registries are the road most modern supply-chain attacks travel: typosquatting, dependency confusion, hijacked maintainer accounts, malicious post-install scripts. There is no composer install or npm install here, so that road doesn't reach you. The entire runtime bill of materials is four items, and the one vendored library (PHPMailer) changes only by a commit you can review.

Is a single-file-config, no-build project actually production-ready?

Being small is not the same as being unfinished. It was hardened across many review passes — Argon2id hashing, parameterized queries everywhere, CSRF tokens, output encoding, session and enumeration defenses, throttling, hardened headers, locked-down deployment paths — and the threat ledger above maps each defense to the file that implements it. Run your own review and a staging pass before launch, as you would with anything that guards accounts.

Can I build my own product on top of it?

That's the intent — it's a starter kit, not a finished app. You get registration, sessions, roles, an admin dashboard, a REST auth API, and first-party analytics as a foundation, then build your product's own pages beside them. It works equally well as the front door to a SaaS, a membership site, an internal tool, or the account layer next to an API or AI backend.

How are passwords and tokens stored?

Passwords are hashed with Argon2id, falling back to bcrypt where unavailable. Reset, verification, remember-me, and API tokens are 256-bit random values stored as SHA-256 digests and compared in constant time, with single-use expiry and rotation. Plaintext secrets never touch the database, and a leaked table yields nothing replayable.

Does it support social sign-in and an API?

Yes to both. OAuth2 sign-in ships for Discord, GitHub, Google, and Microsoft, each with a single-use cryptographic state parameter, PKCE where the provider supports it, and a verified-email requirement; adding another provider is one registry entry. A stateless bearer-token REST API with refresh-token rotation is included for programmatic and mobile clients.

What are the server requirements?

PHP 7.4 or newer, MySQL or MariaDB, and an Apache-compatible host for the included .htaccess rules. Shared hosting works — the whole thing was designed for environments without server-level access, so there's no daemon to run and no build step to trigger on deploy.

Read it. Audit it. Build on it.

The whole thing is public. Star it to follow along, or fork it and make it yours.

An ultra-lightweight, feature-complete, secure-by-default PHP SaaS Website ready to deploy right out-the-box.
Stars
Forks
Issues