# Gapido Backend Code Challenge Python gRPC OTP authentication service with MongoDB, Redis, RabbitMQ, and a Kavenegar SMS adapter. ## Architecture - `auth-service`: async `grpc.aio` API for OTP login, token refresh, token revocation, and RBAC demo methods. - `sms-worker`: RabbitMQ consumer that sends OTP messages through Kavenegar. - MongoDB stores users and refresh-token sessions. - Redis stores OTP hashes, TTL, verification attempts, and OTP request rate limits. - RabbitMQ decouples authentication from SMS delivery. ## Run ```bash cp .env.example .env docker compose up --build ``` The gRPC service listens on `localhost:50051`. RabbitMQ management is available at `http://localhost:15672` with `guest` / `guest`. ## Local Development ```bash python -m venv .venv pip install -e ".[dev]" python -m gapido_auth.tools.generate_proto pytest ``` ## gRPC Methods - `RequestOtp`: public; creates a short-lived OTP and publishes an SMS job. - `VerifyOtp`: public; verifies OTP and returns access and refresh tokens. - `RefreshToken`: public; rotates refresh token and returns a new token pair. - `RevokeRefreshToken`: authenticated; revokes a refresh token session. - `PublicPing`: public. - `UserOnly`: requires any authenticated active user. - `AdminOnly`: requires an authenticated admin. Protected calls use metadata: ```text authorization: Bearer ``` ## Security Notes - OTP codes are generated with `secrets`, stored only as HMAC hashes in Redis, and expire after 120 seconds by default. - OTP requests are rate-limited per mobile number and client identity. - Refresh tokens are opaque random values; only SHA-256 hashes are persisted. - Refresh tokens rotate on use. - Kavenegar is hidden behind an adapter and mocked in tests.