Files
nick-doc/09 - Audits/Task 5.10 Telegram First-Class Authentication.md
2026-05-24 16:15:40 +04:00

128 lines
4.7 KiB
Markdown

---
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 for both Mini App `initData` and browser Login Widget payloads.
## 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.
- 7 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.