Skip to content

Auth — нээлт, token, scope, зөвшөөрөл

OAuth 2.0-тэй төстэй, гэхдээ redirect-гүй: host хүнийг аль хэдийн нэвтрүүлсэн тул launch code нь authorization code-ийн үүргийг гүйцэтгэнэ.

1. Урсгал

Host (Gerege App)              Gerege API                         Mini app frontend        Mini app backend
 │ POST /api/v1/miniapp/apps/{slug}/launch  (хүний session)
 │─────────────────────────────▶│ (төлөв, суваг, scope, consent шалгана)
 │◀── {launch_code, url, …} ────│
 │ url = entry?launch=<code>&path=<p> ачаална ─────────────────▶│
 │                                                              │ POST /your/session {launch}
 │                                                              │────────────────────────▶│
 │                              │◀── POST /api/v1/miniapp/oauth/token (client_id + secret) ─│
 │                              │── {access_token, refresh_token, user:{sub,…}} ──────────▶│
 │                                                              │◀── өөрийн session ──────│
  1. Host → POST /api/v1/miniapp/apps/{slug}/launch {"path"?, "channel"?} → {launch_code, url, expires_at, bridge_methods, testing}. Алдаа: 428 consent_required ({scopes, app} — §5), 403 verification_required / 403 age_restricted (§1.1), 409 maintenance, 403 channel_unavailable, 400 invalid_path, 404.
  2. Host url-ийг ачаална. Frontend launch-ийг URL-аас уншаад history-оос арилгах (history.replaceState) ЗААВАЛ.
  3. Frontend → өөрийн backend. Backend → token endpoint (§2). Backend frontend-д өөрийн session өгнө.
  4. Session дуусвал frontend bridge-ээр getLaunchCode() → шинэ код → 3-р алхам.

1.1 Хэн нээж болох — requires_verified, min_age

Manifest-ийн эдгээр хоёр талбар шалгалт амжилттай болох бүрт registry-д хуулагдаж, нээлт бүрт хэрэгжинэ (батлагдсан апп хатууруулж болно, сулруулж болохгүй):

  • requires_verified: true, эсвэл min_age тавьсан апп-ыг eID-аар баталгаажаагүй хүн нээвэл 403 verification_required (min_age апп бол min_age талбартай) — host хүнийг баталгаажуулах урсгал руу чиглүүлнэ.
  • min_age-тэй апп: нас нь eID-ийн регистрийн дугаараас (YYMMDD, 2000 оноос хойш төрсөнд сар +20) Улаанбаатарын хуанлиар тоологдоно. Хүрэхгүй, эсвэл дугаараас огноо уншигдахгүй бол 403 age_restricted (min_age талбартай). Таны апп хүний насыг, регистрийн дугаарыг хэзээ ч авахгүй — зөвхөн шийдвэр нь хэрэгжинэ.

2. Token endpoint

POST https://geregeapp.mn/api/v1/miniapp/oauth/token

  • Body: application/x-www-form-urlencoded (OAuth) эсвэл application/json (OMAS) — хоёулаа.
  • Client нэвтрэлт: Authorization: Basic base64(client_id:client_secret) (ЗӨВЛӨЖ БАЙНА) эсвэл body-д client_id, client_secret — хоёуланг нь биш (400 invalid_request).
  • Client эхэлж шалгагдана: client-ээ баталж чадаагүй дуудагчид код/token-ий талаар юу ч хэлэхгүй.
grant_type Параметр
authorization_code (эсвэл OMAS-ын launch_code) code=gml_…
refresh_token refresh_token=gma_rt_…

Хариу 200 (Cache-Control: no-store):

{
  "token_type": "Bearer",
  "access_token": "gma_at_…",
  "expires_in": 1800,
  "refresh_token": "gma_rt_…",
  "scope": "profile.basic payments",
  "user": { "ref": "u_9f2c4e7a1b3d5f60718293a4b5c6d7e8", "sub": "u_9f2c4e7a1b3d5f60718293a4b5c6d7e8",
            "verified": true, "locale": "mn" }
}

ref (OMAS-ын нэр) ба sub (OAuth-ын нэр) нь ижил утга — аль нэгийг нь хэрэглэ.

Алдаа — RFC 6749-ийн хэлбэр {"error", "error_description"}:

HTTP error Хэзээ
400 invalid_request body уншигдсангүй, grant_type алга, Basic + body давхар
401 invalid_client client id/secret буруу, апп suspended/disabled, live credential батлагдаагүй апп-д (WWW-Authenticate: Basic)
400 invalid_grant код/refresh token буруу, хугацаа дууссан, ашиглагдсан, өөр апп/орчных
400 unsupported_grant_type дээрх хоёроос өөр
429 — rate limit (минутад 120, burst 30)
500 server_error

Хугацаа ба дүрэм

  • launch code (gml_…): 60 секунд, нэг удаа, тухайн апп-д холбогдсон. Ашиглагдсан кодыг дахин ашиглавал invalid_grant ба тэр кодоор олгосон гинж бүхэлдээ хүчингүй болно.
  • access token (gma_at_…): 30 минут (гинжний хугацаанаас хэтрэхгүй), opaque — бүтцэд нь найдахгүй. Зөвхөн /api/v1/miniapp/*-д хүчинтэй.
  • refresh token (gma_rt_…): rotation — хэрэглэх бүрт шинэ хос, хуучин нь үхнэ; хуучныг дахин ашиглавал бүх гинж хүчингүй. Гинж бүхэлдээ нээлтээс хойш 8 цагаас хэтрэхгүй — дараа нь шинэ нээлт.
  • Хүн апп-аа салгах (consent цуцлах), апп suspend болох үед бүх гинж хүчингүй.
  • Test credential (mapp_test_…): апп батлагдахаас өмнө ч ажиллана, гэхдээ зөвхөн бүртгэсэн гишүүн ба тест хэрэглэгчдийн (console.md §2) нээлтийн кодыг солино. Live credential зөвхөн батлагдсаны дараа.
  • Token-уудыг зөвхөн backend-д хадгална; лог, аналитик, URL-д ХОРИГЛОНО.

3. Хүний мэдээлэл — GET /api/v1/miniapp/me

Authorization: Bearer <access_token> →

{ "ref": "u_9f2c4e…", "sub": "u_9f2c4e…", "verified": true, "locale": "mn",
  "scope": "profile.basic profile.email", "environment": "live", "email": "bat@example.mn" }
  • sub (= ref) = "u_" + hex(HMAC-SHA256(апп-ын salt, хүний ID))[:32] → апп хооронд холбогдохгүй (pairwise), апп дотор тогтмол. Salt апп-ын мөрөнд хадгалагдана — түлхүүр солигдоход хүмүүсийн нэр өөрчлөгдөхгүй. Payment intent-ийн user_ref нь яг энэ утга.
  • verified — хүн eID-аар (ДАН / eID Mongolia) баталгаажсан эсэх. locale — аппын хэл.
  • Утгууд нээлтийн мөчийн хуулбар — хүн зөвшөөрсөн тэр мөчид авсан, ар талд нь шинэчлэгдэхгүй.
  • email зөвхөн profile.email scope олгогдсон үед; phone (E.164, жишээ нь +97699112233) зөвхөн profile.phone олгогдсон бөгөөд хүн дугаараа SMS-ээр баталгаажуулсан үед.
  • Регистрийн дугаар, бүтэн нэр, данс, үлдэгдэл хэзээ ч өгөгдөхгүй. Утас зөвхөн profile.phone-оор, хүн зөвшөөрсөн бөгөөд дугаараа баталгаажуулсан үед.
  • Алдаа: 401 {"error":"invalid_token"} (WWW-Authenticate: Bearer error="invalid_token"). Rate limit минутад 600.

4. Scope

Scope Өгөх зүйл Зөвшөөрөл
profile.basic sub / ref, verified, locale Автомат (нээхэд). Заавал
profile.email Имэйл Consent (host-ийн UI)
profile.phone SMS-ээр баталгаажсан гар утасны дугаар, E.164 (+97699112233); баталгаажуулаагүй бол талбар байхгүй Consent (host-ийн UI)
payments Payment intent үүсгэх/унших/capture/цуцлах/буцаах Автомат — гүйлгээ бүрийг хүн тус бүрт нь баталгаажуулна

given_name (OMAS-ын profile.basic-д байдаг) — «удахгүй»: платформ модульд нэр нийтэлдэггүй. Registry-д зарлаагүй, review-ээр батлагдаагүй scope олгогдохгүй; шинэ scope = дахин review.

  • Consent шаардах scope-ыг хүн зөвшөөрөөгүй бол launch → 428: {"error":"…","code":"consent_required","scopes":["profile.email"],"app":{slug,name,icon_url,developer_name,…}}.
  • Host өөрийн UI-д (mini app дотор БИШ — тэнд зурсан зөвшөөрлийн дэлгэц худал хэлж чадна) асууна → POST /api/v1/miniapp/apps/{slug}/consent {"scopes":[…]} → launch дахин.
  • Хүн Gerege App-аас апп-аа салгаж болно (DELETE …/consent) → бүх token хүчингүй, таны backend-д consent.revoked webhook ирнэ ({object: "consent", user_ref, revoked_at} — webhooks.md §4): тэр user_ref-ийн session-ийг хаа. Webhook-ийг хамгийн боломжоор (best effort) илгээдэг тул найдвартай дохио нь хэвээр — тэр хүний token-оор хийх дараагийн дуудлага invalid_token / invalid_grant авна.

6. Mini app backend-ийн session (зөвлөмж)

  • Frontend-д өгөх session нь cookie-д бүү найд (WebView-д third-party cookie хаалттай байж болно). In-memory token + Authorization header.
  • Session ≤ 8 цаг (refresh гинжний дээд хязгаар). 401 үед frontend getLaunchCode()-оор шинэчилнэ.

English

Launch → token, OAuth-shaped and redirect-free. The host calls POST /api/v1/miniapp/apps/{slug}/launch, loads entry?launch=<gml_…>&path=…; your frontend strips launch from history and hands it to your backend, which calls POST /api/v1/miniapp/oauth/token (form or JSON; Basic auth recommended, body credentials accepted, never both) with grant_type=authorization_code (or launch_code) and code, or grant_type=refresh_token. Launch codes live 60 s and are single use; access tokens 30 min; refresh tokens rotate and the whole chain ends 8 h after the launch; replaying a used code or refresh token revokes the chain. Test credentials redeem only the registering member's and the test users' launches; live credentials work after approval. The token response's user and GET /me carry ref and sub (the same pairwise value), verified, locale, and on /me also scope, environment, email with profile.email and phone (E.164, SMS-verified; absent if the person has none) with profile.phone — both by consent. Launch refuses with 403 verification_required / age_restricted for apps whose manifest sets requires_verified / min_age. Disconnecting sends consent.revoked. given_name is not available yet.