Authentication service with OTP (Redis) + JWT and user management.
Implements Clean/Hexagonal Architecture, fully containerized with Docker (MySQL, Redis, phpMyAdmin).
- 🔑 OTP via Redis (hash + TTL + attempts + blocklist)
- 🔒 JWT HS256 with standard claims (
sub,phone,iat,exp) - 🗄 MySQL + GORM (AutoMigrate)
- ⚡ Rate limit & temporary blocking
- 📖 Swagger UI
- ⚙️ Config via ENV (Viper)
- 📝 Structured logging (Zerolog)
- Docker & Docker Compose
- (Optional) GNU
make
cp infra/.env.example infra/.env
cp src/.env.example src/.envEdit infra/.env → MySQL root password & ports.
Edit src/.env → DB/Redis/JWT configs (must match infra).
make up
# or
docker compose --env-file infra/.env -f infra/docker-compose.dev.yml up -d --buildmake migrate- API → http://localhost:8080/healthz
- DB → /health/db
- Redis → /health/redis
- phpMyAdmin → http://localhost:8081 (Server: mysql)
http://localhost:8080/swagger/index.html
infra/ → docker-compose, Dockerfiles, env
src/
cmd/api/main.go
cmd/migrate/main.go
internal/
adapters/ (http, db, cache, jwt)
core/ (domain, ports, services)
pkg/ (config, db, logger, util)
docs/ (swagger)
migrations/
Makefile
1) Request OTP
curl -X POST http://localhost:8080/v1/auth/otp/request -H "Content-Type: application/json" -d '{"phone":"09120000000"}'
# → 204 No Content (OTP printed in logs on dev)2) Verify OTP & Get Token
curl -X POST http://localhost:8080/v1/auth/otp/verify -H "Content-Type: application/json" -d '{"phone":"09120000000","otp":"<OTP>"}'3) Current User
curl http://localhost:8080/v1/users/me -H "Authorization: Bearer <TOKEN>"4) List Users (search + pagination)
curl "http://localhost:8080/v1/users?search=0912&page=1&per_page=20" -H "Authorization: Bearer <TOKEN>"make up→ Start servicesmake down→ Stop servicesmake logs→ Tail logsmake ps→ Show containersmake migrate→ Run DB migrationsmake swagger→ Regenerate Swagger docsmake restart→ Restart stack
- Use a strong, private
JWT_SECRETin production.