Slim 4 + SQLite todo-list API providing email/password registration, login, and an authenticated GET /me endpoint. Stateless HS256 JWTs, bcrypt password hashing, uniform JSON error envelope, and a SQL migration runner. Includes PHPUnit feature tests and stage-1 docs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2.5 KiB
2.5 KiB
Stage 1 — Authentication API
Status: done and verified end-to-end (PHPUnit feature tests + a live curl
run against the built-in server).
What's there
A Slim 4 REST API on SQLite with JWT bearer authentication.
| Method | Path | Purpose |
|---|---|---|
| GET | /api/health |
liveness check |
| POST | /api/auth/register |
create account, returns user + token |
| POST | /api/auth/login |
exchange email/password for a token |
| GET | /api/me |
current user (requires Authorization: Bearer <jwt>) |
- Passwords are hashed with
password_hash()(bcrypt). Validation is email-format plus an 8–72 character password. Login returns a single generic "Invalid email or password" message so it does not leak which emails exist. - Emails are stored lower-cased in a
UNIQUE COLLATE NOCASEcolumn; duplicate registration returns409. - Errors always come back as
{ "error": { "message": ..., "details"?: ... } }via ../src/Http/JsonErrorHandler.php. - Tokens are stateless HS256 JWTs. The signing secret comes from
JWT_SECRET, or is auto-generated intostorage/secret.keyon first run. - Migrations are plain SQL files in ../migrations/, applied
idempotently by ../bin/migrate.php and tracked in a
schema_migrationstable.
Dependency note
firebase/php-jwt is pinned to ^7.0 — Composer blocks 6.10–6.11 for a
published security advisory (PKSA-y2cr-5h3j-g3ys).
Key files
- ../src/bootstrap.php — app wiring + routes
- ../src/Http/Controllers/AuthController.php — register / login / me
- ../src/Auth/JwtService.php, ../src/Auth/AuthMiddleware.php
- ../src/Repository/UserRepository.php
- ../src/Support/Config.php, ../src/Support/Database.php
- ../tests/AuthTest.php — 6 passing feature tests
Run it
composer install && composer migrate && composer serve # http://localhost:8080
Local toolchain
This machine has no php/composer binary. Tooling was run through the official
Composer container image, which bundles PHP + Composer + pdo_sqlite +
mbstring:
podman run --rm -v "$PWD":/app:Z -w /app docker.io/library/composer:2 install
podman run --rm -v "$PWD":/app:Z -w /app docker.io/library/composer:2 vendor/bin/phpunit