--- title: Task 5.10 Telegram First-Class Authentication tags: [audit, taskmaster, telegram, auth, testing] --- # Task 5.10 Telegram First-Class Authentication Date: 2026-05-24 ## Scope Task 5.10 implemented Telegram as a first-class Amanat auth provider. - Backend now exposes `POST /api/auth/telegram`. - The endpoint accepts Telegram Mini App `initData` or Telegram Login Widget payloads. - Telegram signatures are verified server-side. - Telegram-only users can be created without email/password. - Standard Amanat JWT and refresh tokens are returned. - Frontend Mini App sessions auto-authenticate from raw signed `initData`. - The web login view includes a Telegram continuation button. ## Backend Implementation Changed project: `backend` - `src/models/User.ts` - `email` is now optional with a sparse unique index. - Added `authProvider: "email" | "google" | "telegram"`. - Added `telegramVerified`. - `src/models/TelegramLink.ts` - Added `login_widget` as a supported source. - `src/services/telegram/telegramService.ts` - Added Telegram Login Widget verification. - Added normalized Telegram auth identity helpers. - `src/services/auth/authController.ts` - Added `telegramAuth`. - Auto-provisions Telegram users with nullable email. - Rejects replayed Mini App data, stale auth dates, invalid signatures, bot accounts, blocked links, and inactive users. - `src/services/auth/authRoutes.ts` - Added public `POST /telegram`, mounted externally as `/api/auth/telegram`. ## Frontend Implementation Changed project: `frontend` - `src/lib/axios.ts` - Added `/auth/telegram` as a public endpoint. - Added `endpoints.auth.telegram`. - `src/auth/context/jwt/action.ts` - Added `signInWithTelegram`. - Stores returned access/refresh tokens using the existing auth storage path. - `src/sections/telegram/telegram-mini-app-shell.tsx` - Auto-authenticates Mini App sessions once from raw `initData`. - Shows an onboarding dialog for newly provisioned Telegram accounts. - Keeps standard sign-in/dashboard fallbacks. - `src/auth/components/form-socials.tsx` - Added Telegram icon button. - `src/auth/view/jwt/jwt-sign-in-view.tsx` - Added Telegram sign-in handler. ## Security Notes - Frontend never trusts `initDataUnsafe` for auth; it only sends raw signed `initData`. - Backend validates Telegram HMAC signatures using the configured bot token. - Mini App `auth_date` freshness and replay window are enforced before JWT issuance. - Login Widget `auth_date` freshness is enforced. - Telegram bot accounts are rejected. - Blocked `TelegramLink` records are rejected with 403. - Telegram phone numbers are neither requested nor persisted. - High-risk escrow and wallet actions still use the existing protected API and step-up rules. ## Verification Backend: ```bash npm run typecheck npx jest __tests__/telegram-auth.test.ts __tests__/telegram-service.test.ts --runInBand --forceExit ``` Result: - Backend typecheck passed. - `__tests__/telegram-auth.test.ts` passed. - `__tests__/telegram-service.test.ts` passed. - 14 targeted backend tests passed. Frontend: ```bash npm test -- __tests__/auth/telegram-auth-action.test.ts __tests__/sections/telegram/telegram-mini-app-shell.test.tsx --runInBand npx tsc --noEmit -p tsconfig.json ``` Result: - Targeted frontend Jest tests passed. - 6 targeted frontend tests passed. - Full frontend typecheck still reports unrelated pre-existing errors in payment UI code outside Task 5.10: - `src/components/payment/shkeeper-payment-widget.tsx` - `src/web3/components/provider-payment.tsx` ## Acceptance Coverage | Requirement | Status | | --- | --- | | New Telegram user auto-provisions and receives JWT | Covered by backend test | | Returning user authenticates via Mini App initData | Covered through same route and link lookup | | Returning user authenticates via Login Widget | Covered by backend test | | Replayed Mini App initData rejected | Covered by backend test | | Stale `auth_date` rejected | Covered by backend test | | Blocked Telegram account returns 403 | Covered by backend test | | Existing email/password users unaffected | Covered by backend test | | Email optional for Telegram users | Covered by backend test and sparse user model | | `isNewUser` triggers onboarding overlay | Covered by frontend shell behavior | | High-risk actions retain step-up requirements | No high-risk action code changed | ## Operational Follow-up If a deployed MongoDB already has an old non-sparse unique `email` index, replace it with the sparse unique index before creating multiple Telegram-only users: ```js db.users.dropIndex("email_1") db.users.createIndex({ email: 1 }, { unique: true, sparse: true }) ``` Run this only after confirming the existing index name in the target database.