# OTP login (legal & production)

## What went wrong if a “wrong digit” still logged in

Two different cases:

| Mistake | What happens |
|---------|----------------|
| **Wrong phone** (e.g. `…9302` instead of `…9303`) | That is a **different account**. OTP must be requested for the number you type. You only “get in” if you also enter the **correct OTP for that wrong number** (SMS to that SIM, or an old demo bypass). |
| **Wrong OTP** (typo in the 6-digit code) | Should **fail**. Backend requires an **exact 6-digit** match (secure compare). |

If **`123456`** worked on your real number on Render, that was the old **demo OTP** behavior. **Production now disables `123456` unless you explicitly set `ENABLE_DEMO_OTP=true`.** Do not enable that on the public Render service.

## Interim mode (no SMS budget yet)

1. Server generates a **random 6-digit OTP**, stores it (Redis or DB on Aiven), **10 minute** TTL.
2. `POST /verify-otp` must send the **exact** code for that phone (one-time use).
3. Until Fast2SMS is configured, set on Render:

   ```bash
   OTP_INCLUDE_IN_RESPONSE=true
   ```

   Then `POST /request-otp` includes `"otp": "482910"` in JSON so the app can show it (or read Render logs). **Turn this off when DLT SMS is live.**

4. Do **not** set `ENABLE_DEMO_OTP` on public production unless you need fixed `123456` for demo phones only.

## Production rules (after security update)

- Real users: **random 6-digit OTP**, stored server-side, sent by **SMS**.
- **`123456`**: only for phones in the demo allowlist **and** only when `ENABLE_DEMO_OTP=true` (use on local/staging, not public prod).
- **5 wrong OTPs** → 15-minute lock for that user.
- Rate limits: per IP and per phone on `/request-otp` and `/verify-otp`.

## Free / low-cost SMS in India (recommended: Fast2SMS)

This repo already supports **[Fast2SMS](https://www.fast2sms.com/)** (`app/services/fast2sms_provider.rb`).

1. Sign up at Fast2SMS (wallet credits; often enough for early testing).
2. Complete **DLT** registration (TRAI requirement for commercial SMS in India — not optional for production marketing/OTP templates).
3. Create an **OTP route / template** and note the **OTP ID**.
4. On Render → **Environment**:

   | Variable | Value |
   |----------|--------|
   | `FAST2SMS_API_KEY` | from Fast2SMS dashboard |
   | `FAST2SMS_OTP_ID` | your DLT OTP template id |

5. Redeploy. Request OTP on a **real** number — SMS should arrive; only that code works for **that** phone.

Without these env vars, production **does not** send SMS (OTP is only logged on the server). Users cannot guess a valid code except by brute force (blocked by lockout + throttles).

## Other providers (alternatives)

| Provider | Notes |
|----------|--------|
| **MSG91**, **Twilio**, **AWS SNS** | Similar: API key + Indian DLT where applicable |
| **Firebase Phone Auth** | Client-side verification; different architecture (not wired in this API today) |

## Render checklist for real OTP

- Do **not** set `ENABLE_DEMO_OTP` on public production.
- Set `FAST2SMS_API_KEY` + `FAST2SMS_OTP_ID`.
- Optional: `REDIS_URL` for OTP in Redis (else OTP stored on user row in Aiven).
- Run migrations (`otp_code`, lockout columns) via deploy `db:prepare`.

## Admin

Do not mark real customer users as **internal** in ActiveAdmin (`/admin`) — that flag is for demo accounts only.
