Document Telegram first-class auth
This commit is contained in:
127
09 - Audits/Task 5.10 Telegram First-Class Authentication.md
Normal file
127
09 - Audits/Task 5.10 Telegram First-Class Authentication.md
Normal file
@@ -0,0 +1,127 @@
|
||||
---
|
||||
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.
|
||||
Reference in New Issue
Block a user