1.7 KiB
Implementation Decisions
Python gRPC Service
The challenge explicitly required Python with gRPC. The auth boundary is therefore a grpc.aio service instead of REST. A separate FastAPI demo service was added only as a browser-friendly client.
OTP Storage
OTP codes are never stored in plaintext. Redis stores HMAC hashes with a short TTL, attempt counters, and request rate-limit counters. This keeps OTP state fast, temporary, and easy to expire.
Token Model
Access tokens are signed JWTs with short TTLs. Refresh tokens are opaque random values, stored only as hashes in MongoDB, and rotated on every use.
RabbitMQ SMS Dispatch
SMS delivery is asynchronous. The auth service publishes a durable message and returns quickly. The worker uses manual acknowledgement, bounded retries, and a dead-letter queue for failed deliveries.
SMS Provider Strategy
Kavenegar, SMS.ir, and debug delivery implement the same SmsClient port. The provider is selected through configuration, which keeps the worker closed for modification when adding providers.
Demo Service
Browsers do not speak native gRPC directly. A small FastAPI backend-for-frontend demonstrates how another microservice consumes the auth service through gRPC while serving a minimal UI.
Local vs Production Compose
The base Compose file is production-safe and keeps service ports private. docker-compose.local.yml publishes developer ports. docker-compose.prod.yml adds Caddy as the only public entrypoint.
Caddy Reverse Proxy
Caddy was chosen for automatic HTTPS and a compact configuration. Production serves only https://gapido.amiirkhl.ir; internal service ports are not published.