# GoodGo Platform - Authentication Quick Reference ## ๐Ÿ”‘ Key Points at a Glance ### Password Hashing ``` Algorithm: bcrypt Salt Rounds: 12 (env: BCRYPT_ROUNDS) Min Length: 8 characters Example: bcrypt.hash('password', 12) ``` ### Phone Numbers (Vietnamese) ``` Valid Formats: 0900000001, 84900000001, +84900000001 Normalized: +84900000001 Regex: /^(?:\+84|84|0)(3[2-9]|5[2689]|7[06-9]|8[1-9]|9[0-9])\d{7}$/ File: apps/api/src/modules/shared/utils/vietnam-phone.validator.ts ``` ### Email ``` Regex: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ Normalization: lowercase + trim Storage: admin@goodgo.vn ``` ### PII Encryption ``` Algorithm: AES-256-GCM Key: 32 bytes (64 hex chars) Encrypted: email, phone, kycData Searchable: email โ†’ emailHash (HMAC-SHA256) phone โ†’ phoneHash (HMAC-SHA256) Env Var: FIELD_ENCRYPTION_KEY ``` ### User Login ``` Username: phone (normalized) Password: plain text Lookup: by phoneHash (unique index) Required: isActive = true, passwordHash โ‰  null Response: tokens (or MFA challenge) ``` ### User Roles ``` BUYER - Search, inquire, offer (default) SELLER - Create listings AGENT - Professional agent ADMIN - Full access ``` ### MFA ``` TOTP: otplib (RFC 6238) Period: 30 seconds Digits: 6 Backup Codes: 10 ร— 8 chars (A-Z no OI, 2-9 no 01) Hashing: HMAC-SHA256 (not bcrypt) ``` --- ## ๐Ÿ“‹ Creating a Login-Capable Admin User ### 5-Step Process **1. Normalize phone** ```typescript phone = '0900000001' โ†’ '+84900000001' ``` **2. Derive HMAC key** ```typescript hmacKey = crypto.hkdfSync('sha256', Buffer.from(encryptionKey, 'hex'), Buffer.alloc(0), Buffer.from('goodgo-field-hash', 'utf8'), 32) ``` **3. Compute hashes** ```typescript phoneHash = crypto.createHmac('sha256', hmacKey).update('+84900000001').digest('hex') emailHash = crypto.createHmac('sha256', hmacKey).update('admin@goodgo.vn').digest('hex') ``` **4. Hash password** ```typescript passwordHash = await bcrypt.hash('AdminPassword123', 12) ``` **5. Create user** ```typescript await prisma.user.create({ data: { id: 'admin-seed-001', phone: '+84900000001', phoneHash, email: 'admin@goodgo.vn', emailHash, passwordHash, fullName: 'Admin', role: 'ADMIN', kycStatus: 'VERIFIED', isActive: true, totpEnabled: false, totpBackupCodes: [], }, }); ``` --- ## ๐Ÿงช Test Login ```bash curl -X POST http://localhost:3000/auth/login \ -H "Content-Type: application/json" \ -d '{ "phone": "0900000001", "password": "AdminPassword123" }' ``` **Success Response:** ```json { "requiresMfa": false, "tokens": { "accessToken": "eyJ...", "refreshToken": "eyJ...", "expiresIn": 3600 } } ``` --- ## โš ๏ธ Common Issues | Issue | Fix | |-------|-----| | User can't login | Check: `passwordHash` โ‰  null, `isActive` = true | | "Invalid phone" | Phone must match regex (mobile only) | | Hash mismatch | Verify `FIELD_ENCRYPTION_KEY` is consistent | | MFA issue | Verify `MFA_BACKUP_CODE_SECRET` env var | | PII not encrypted | Verify key is exactly 32 bytes (64 hex chars) | --- ## ๐Ÿ“ Key Files | File | Purpose | |------|---------| | `hashed-password.vo.ts` | bcrypt hashing | | `vietnam-phone.validator.ts` | Phone validation | | `field-encryption.ts` | AES-256-GCM encryption | | `local.strategy.ts` | Login endpoint | | `mfa.service.ts` | TOTP / backup codes | | `user.entity.ts` | User domain model | | `prisma-user.repository.ts` | User persistence | | `seed.ts` | Seed script | --- ## ๐Ÿ” Checklist for Seed User - [ ] Password โ‰ฅ 8 chars - [ ] Phone matches regex - [ ] Phone normalized: +84... - [ ] Phone hashed: HMAC-SHA256 - [ ] Email lowercased - [ ] Email hashed: HMAC-SHA256 - [ ] Password hashed: bcrypt (12 rounds) - [ ] `isActive: true` - [ ] `passwordHash` โ‰  null - [ ] `totpEnabled: false` - [ ] `totpBackupCodes: []` --- ## ๐Ÿ“š Full Documentation Files 1. **AUTHENTICATION_GUIDE.md** - Complete technical reference 2. **AUTH_IMPLEMENTATION_CHECKLIST.md** - Implementation checklist & troubleshooting 3. **SEED_GENERATION_SCRIPT.ts** - Ready-to-use seed script 4. **QUICK_REFERENCE.md** - This file --- **Last Updated:** April 12, 2026 **Status:** โœ… Production-Ready