OWNER gates — Google · Firebase · SMS · MoMo · EAS (WELIFE)
Snapshot tổng:
STATUS.md(2026-08-14). Bạn đăng ký dịch vụ + lấy credential. Agent cấu hình code/IPN/smoke sau khi secret có sẵn. Không commit secret. Không đặt secret vàoEXPO_PUBLIC_*. Paste map:OWNER-WIRE-CHECKLIST.md(WP-OWNER-WIRE-01).
Thứ tự khuyến nghị: Google → Firebase Admin SA → SMS OTP · VNPay e2e → MoMo sandbox.
Firebase Hybrid (IdP): OWNER-FIREBASE-HYBRID.md · project welife-2412.
Status snapshot (2026-08-14)
| Gate | Status | Ghi chú |
|---|---|---|
| Google OAuth | DONE | WP-AUTH-GOOGLE-LIVE-01 IMP |
| Firebase public (mobile) | WIRED | EXPO_PUBLIC_FIREBASE_WEB_APP_ID SET (1:3032…:web:…) · Android id giữ trong google-services.json |
| Firebase Web + Auth deploy | OWNER verify | Web App ID đã wire · Auth/Firestore deploy vẫn cần firebase login nếu chưa làm |
| Code Auth+Firestore | IMP | WP-AUTH-FIREBASE-WEB-01 — Firebase-first + Nest JWT |
| Firebase Admin SA | OWNER (optional) | VPS/api/.env CLIENT_EMAIL/PRIVATE_KEY MISSING → bridge off (EXPO_PUBLIC_FIREBASE_BRIDGE=0) |
| SMS (eSMS) | KEYS ON VPS | SMS_PROVIDER=esms · brand WELIFE · ready 2026-08-14 · re-smoke PASS preflight 2026-08-19 · e2e OTP phone OWNER (no_sms) |
| VNPay sandbox | CREATE PASS | preferred · init 201 · re-smoke PASS 2026-08-17 · OWNER còn mở payUrl → thanh toán test → ví |
| MoMo sandbox | CREATE FAIL | Keys SET · create 400 merchant inactive · 2026-08-14 · không preferred |
| P7a harden (Swagger/Wallet) | IMP | /docs 404 · wallet credit false · sync ép lại mỗi deploy |
| Email OTP (Gmail SMTP) | WIRED PROD | VPS smtp.gmail.com:465 · mailSent=true · scripts/sync-gmail-smtp-vps.mjs · MAIL-DNS |
| OWNER wire checklist | PARTIAL | STATUS · Pay create PASS · MoMo FAIL · SMS e2e · EAS DONE |
| EAS cloud APK | DONE | CON+DRV+PAR preview · EAS-BUILD |
Bạn làm tiếp (chọn 1):
- Pay VNPay: mở
payUrlsandbox (app nạp ví) → thanh toán test → xác nhận ví + return - SMS: OTP SĐT thật (eSMS) → xác nhận tin nhắn đến
- MoMo: sửa merchant sandbox trên portal rồi nhắn agent smoke lại
- EAS:
cloud APKDONE CON+DRV+PAR — cài device · smoke login/API (EAS-BUILD) - (Tuỳ chọn) Paste Firebase Admin SA nếu cần Nest
/auth/firebasebridge
EAS cloud (WP-EAS-01 / DRV / PAR)
| App | Expo | Status |
|---|---|---|
| CON | welife-consumer | APK ready — 845b6a3d |
| DRV | welife-driver | APK ready — 18716e82 |
| PAR | welife-partner | APK ready — e0e55329 |
Windows: $env:NODE_OPTIONS='--use-system-ca' trước mọi eas / npx eas-cli. Chi tiết: EAS-BUILD.md.
0. Phân tách env (hard rule)
| Surface | Được phép | Cấm |
|---|---|---|
mobile/.env · .env.local |
Chỉ EXPO_PUBLIC_* (Client ID public, API URL) |
Mọi *_SECRET · MoMo keys · SMS keys · JWT |
api/.env |
JWT, DB, Google audiences, MoMo, SMS, SMTP | — |
| Git | *.env.example |
.env / .env.local (đã gitignore) |
.env
.env.*
!.env.example
!.env.*.example
1. Google Login (OWNER #1 — DONE)
Cloud Console
- Google Cloud Console → APIs & Services → Credentials
- Tạo OAuth 2.0 Client riêng cho từng nền tảng (Google khuyến nghị):
- Web application
- Android (package
cloud.minhtien.welife+ SHA-1) - iOS (bundle
cloud.minhtien.welife)
WELIFE hiện tại = ID Token flow (không cần client secret)
App lấy Google idToken → POST /api/v1/auth/google → API verify audience bằng google-auth-library.
Không dùng Authorization Code + GOOGLE_CLIENT_SECRET (trừ khi sau này đổi sang server-side code flow).
Redirect FE (OAuth Web client): https://auth.expo.io/@adminmarketingnx/welife-consumer.
Không dùng welife://oauth (Google chặn custom scheme) và không dùng @…/welife (sai slug).
Env
# mobile/.env.local (PUBLIC — Client ID không phải secret)
EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID=xxxx.apps.googleusercontent.com
EXPO_PUBLIC_GOOGLE_ANDROID_CLIENT_ID=xxxx.apps.googleusercontent.com
EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID=xxxx.apps.googleusercontent.com
# api/.env (verify audience — thường = Web Client ID)
GOOGLE_CLIENT_ID=xxxx.apps.googleusercontent.com
# Tuỳ chọn thêm audience native + **Firebase OAuth Web client**
# (bắt buộc nếu login Google qua Firebase popup trên web — aud ≠ WELIFE Web Client):
# GOOGLE_CLIENT_IDS=web....,android....,ios....,3032…firebase-web….apps.googleusercontent.com
# GOOGLE_ANDROID_CLIENT_ID=
# GOOGLE_IOS_CLIENT_ID=
Cấm tuyệt đối:
EXPO_PUBLIC_GOOGLE_CLIENT_SECRET=... # ❌ lộ trong APK
GOOGLE_CLIENT_SECRET / GOOGLE_REDIRECT_URI chỉ cần nếu sau này chuyển sang server Authorization Code — hiện không dùng.
Sau khi điền:
$env:NODE_OPTIONS='--use-system-ca' # Windows TLS — bắt buộc để verify Google JWKS
npm run env:check
# restart API + npx expo start -c
Nếu /auth/google trả TLS/CA hoặc N audience attempt(s) failed dù Client ID đúng: API đang chạy không có --use-system-ca (corp AV MITM). npm run api:prod:local / start:prod:local đã tự gắn flag này.
Agent: WP-AUTH-GOOGLE-LIVE-01 IMP (2026-08-10).
1b. Firebase Web app + Auth/Firestore deploy (OWNER #NEXT)
Chi tiết: OWNER-FIREBASE-HYBRID.md §0.
$env:NODE_OPTIONS='--use-system-ca'
npx -y firebase-tools@latest login --no-localhost
node scripts/firebase-owner-setup.mjs
# merge mobile/.env.firebase-web.snippet → mobile/.env.local
1c. Firebase Admin SA (optional — Nest /auth/firebase)
# api/.env
FIREBASE_CLIENT_EMAIL=
FIREBASE_PRIVATE_KEY=
# mobile/.env.local
EXPO_PUBLIC_FIREBASE_BRIDGE=1
Google login không bắt buộc bước này (Nest /auth/google).
2. SMS OTP (OWNER — READY keys · e2e thủ công)
VPS: SMS_PROVIDER=esms + ESMS_* SET · brand WELIFE · OWNER-SMS-READY-2026-08-14.
Owner bỏ qua tạm (local): SMS_PROVIDER=console + OTP email.
Chốt go-live: eSMS (đang bật) · Twilio · HTTP bridge.
Flow an toàn
Mobile → POST /auth/.../otp → API generate + hash Redis → SMS provider → user
Mobile → POST verify → API verify (Mobile KHÔNG gọi SMS provider)
Env (chỉ api/.env)
eSMS (khuyến nghị VN):
SMS_PROVIDER=esms
ESMS_API_KEY=
ESMS_SECRET_KEY=
ESMS_BRAND_NAME=WELIFE
ESMS_SMS_TYPE=2
Twilio (tên biến đúng code WELIFE):
SMS_PROVIDER=twilio
TWILIO_ACCOUNT_SID=
TWILIO_AUTH_TOKEN=
TWILIO_FROM_NUMBER=
Local: SMS_PROVIDER=console + email OTP (OTP_CHANNEL=email) vẫn OK.
Agent tiếp: WP-AUTH-SMS-01 e2e khi key sẵn (không schedule trước MoMo).
3. Pay live — VNPay sandbox PRIMARY (2026-08-10)
PAYMENTS_MOCK=false · default gateway VNPAY (preferred trên /payments/providers).
Smoke: create → payUrl sandbox.vnpayment.vn · report.
# api/.env
PAYMENTS_MOCK=false
VNPAY_TMN_CODE=
VNPAY_HASH_SECRET=
VNPAY_URL=https://sandbox.vnpayment.vn/paymentv2/vpcpay.html
VNPAY_RETURN_URL=
# VNPAY_IPN / return cần URL public khi test callback đầy đủ
MoMo (OWNER — CREATE FAIL 2026-08-14)
MoMo env SET (sandbox + IPN public) nhưng gateway reject merchant — không preferred.
Report: OWNER-MOMO-FAIL-2026-08-14.
Khi có key / merchant sandbox đúng:
MOMO_PARTNER_CODE=
MOMO_ACCESS_KEY=
MOMO_SECRET_KEY=
MOMO_ENV=sandbox
MOMO_ENDPOINT=https://test-payment.momo.vn/v2/gateway/api/create
Flow: App → API ký → cổng → IPN/return → PAID. Secret chỉ trên API.
4. Production split (tóm tắt)
Mobile — public only
EXPO_PUBLIC_ENV=production
EXPO_PUBLIC_API_URL=https://api.welife.cloud/api/v1
EXPO_PUBLIC_WS_URL=https://api.welife.cloud
EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID=
EXPO_PUBLIC_GOOGLE_ANDROID_CLIENT_ID=
EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID=
API — secrets
GOOGLE_CLIENT_ID=
# MoMo / SMS / JWT / DB — xem api/.env.production.example
PAYMENTS_MOCK=false
SMS_PROVIDER=esms
ALLOW_INTERNAL_WALLET_CREDIT=false
5. Stop-gate bảng
| Gate | OWNER làm | Agent làm sau khi có key |
|---|---|---|
| OAuth Web/Android/iOS — DONE | WP-AUTH-GOOGLE-LIVE-01 IMP |
|
| Firebase SA | Service account JSON → api/.env |
Smoke POST /auth/firebase + bridge |
| SMS | Chọn/đăng ký provider + key | OTP send/verify e2e |
| Pay | MoMo merchant + sandbox keys | Payment + IPN + HMAC verify |
| Production | Secret lên VPS (chmod 600) | Deploy + smoke |
Bạn không cần tự code ba phần này — chỉ đăng ký dịch vụ và đưa credential vào api/.env / mobile/.env.local (không commit).