@gerege-systems/eid-mongolia-sdk 0.12.1 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -86
- package/dist/button.cjs +952 -0
- package/dist/button.d.cts +79 -0
- package/dist/button.d.ts +79 -0
- package/dist/button.js +923 -0
- package/dist/index.cjs +350 -270
- package/dist/index.d.cts +122 -127
- package/dist/index.d.ts +122 -127
- package/dist/index.js +349 -266
- package/package.json +12 -4
package/README.md
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
RP-API v3, Smart-ID нийцтэй. Бүрэн баримт: <https://developer.eidmongolia.mn/>.
|
|
6
6
|
|
|
7
7
|
> ⚠️ SDK **backend**-д ажиллана: бүх дуудлага API secret (`rp_sk_…`)-ээр баталгаажна, secret-ийг браузер/гар утсанд
|
|
8
|
-
> хэзээ ч задлахгүй. Браузерт зөвхөн таны backend-ийн өгсөн холбоос/QR/товч харагдана — «eID-ээр нэвтрэх» товч
|
|
9
|
-
>
|
|
10
|
-
>
|
|
8
|
+
> хэзээ ч задлахгүй. Браузерт зөвхөн таны backend-ийн өгсөн холбоос/QR/товч харагдана — «eID-ээр нэвтрэх» товч
|
|
9
|
+
> (`/button`) ч таны backend-ийг л дуудна (§1a). `@gerege-systems/eid-mongolia-sdk/browser`-ийн legacy device-link
|
|
10
|
+
> туслахууд 2026-10-07-оос ажиллахгүй (§4).
|
|
11
11
|
|
|
12
12
|
## Суулгах
|
|
13
13
|
|
|
@@ -22,108 +22,104 @@ Node.js ≥ 22 (global `fetch`, `node:crypto`).
|
|
|
22
22
|
RP-г eID Mongolia-гийн оператор бүртгэнэ — хүсэлтээ <eIDsupport@gerege.com> эсвэл 7777-3773-аар гаргана
|
|
23
23
|
(нийтийн `POST /v3/rp-applications` 2026-10-14-нөөс засвартай: `503 rp_applications_maintenance`). Оператор
|
|
24
24
|
баталсны дараа **relyingPartyUUID** ба **API secret** (`rp_sk_…`) олгогдоно; secret **зөвхөн нэг удаа** харагдана.
|
|
25
|
-
Шаардлагатай мэдээлэл (байгууллага, зорилго `AUTH`/`SIGN`, `callbackHosts
|
|
25
|
+
Шаардлагатай мэдээлэл (байгууллага, зорилго `AUTH`/`SIGN`, `callbackHosts`…):
|
|
26
26
|
<https://developer.eidmongolia.mn/#registration>.
|
|
27
27
|
|
|
28
|
-
## 1a. «eID-ээр нэвтрэх»
|
|
28
|
+
## 1a. «eID-ээр нэвтрэх» — нэг товч
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
(
|
|
33
|
-
хуудасгүйгээр шууд eID апп нээгдэнэ. Гэрээ: <https://developer.eidmongolia.mn/#oidc>.
|
|
30
|
+
Smart-ID-тэй RP-үүдийн хэв маяг: хөтөчид **нэг товч**, бүх eID дуудлага таны **backend**-д (API secret-ээр). SDK хоёр
|
|
31
|
+
хэсэг өгнө — backend-ийн бэлэн урсгал `createEidLogin` ба хөтчийн товч `@gerege-systems/eid-mongolia-sdk/button`.
|
|
32
|
+
Доорх нь §2/§4-ийн RP-API (device link v3, push, `ResponseValidator`)-ийг л ашиглана; тусдаа протокол биш.
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
| Хаана | Юу болно |
|
|
35
|
+
|---|---|
|
|
36
|
+
| Desktop хөтөч | Цонх: QR (секунд тутам шинэчлэгдэнэ) + «регистрийн дугаараар утас руу мэдэгдэл» (push), үлдсэн хугацаа, шууд төлөв |
|
|
37
|
+
| Утасны хөтөч | Товч → `start?mode=web2app` → сервер 302 → eID апп (Web2App). Апп баталгаажуулаад `/auth/eid/callback` руу буцаана |
|
|
38
|
+
| Backend | session эхлүүлэх, QR угсрах (`sessionSecret` серверт), poll, `validateAuth` (гинж + ACSP_V2 + `flowType` + Web2App-д `userChallengeVerifier`) → таны `onSuccess` |
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
RP-д `AUTH` эрх, OIDC асаалттай, `redirect_uri` (https, ≤ 10) бүртгэлтэй байна — authorize/token-ий `redirect_uri`
|
|
42
|
-
бүртгэлтэйтэй **тэмдэгт бүрээрээ** таарах ёстой. Иргэний ETSI дугаар (`pnomn` claim) хэрэгтэй бол `PNOMN` эрх
|
|
43
|
-
хүсэж, `scope: "openid pnomn"`. Token endpoint-д RP-ийн IP allowlist мөрдөгдөнө; `requireMtls` RP OIDC ашиглахгүй.
|
|
40
|
+
**Endpoint-ууд** (`/auth/eid` дор — eID сервер Web2App буцах замыг үргэлж `/auth/eid/callback` болгож нормчилдог):
|
|
44
41
|
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
| | Хүсэлт | Хариу |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| `POST /auth/eid/start` | `{"mode":"qr"}` эсвэл `{"mode":"push","idCode":"УБ12345678"}` (JSON заавал) | `{mode, vc, qr?, expiresIn}` + `Set-Cookie: eid_login` |
|
|
45
|
+
| `GET /auth/eid/start?mode=web2app` | утасны хөтөч (товчны навигаци) | `302` → eID апп |
|
|
46
|
+
| `GET /auth/eid/status` | cookie | `PENDING` (+шинэ `qr`, `expiresIn`) · `WAIT_CALLBACK` · `OK` (`redirect`, `data`) · `FAILED` (`error`) · `EXPIRED` |
|
|
47
|
+
| `GET /auth/eid/callback` | апп буцаана: `?sessionId&userChallengeVerifier` | `303` → `onSuccess`-ийн `redirect` / `successRedirect`, алдаа бол `failureRedirect?eid_error=<код>` |
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
clientId: process.env.EID_RP_UUID!,
|
|
50
|
-
clientSecret: process.env.EID_SECRET!, // rp_sk_… — зөвхөн backend
|
|
51
|
-
redirectUri: "https://bank.example.mn/auth/eid/callback",
|
|
52
|
-
// issuer анхдагч https://login.eidmongolia.mn, scope анхдагч "openid"
|
|
53
|
-
});
|
|
49
|
+
**Backend** (нэг instance-ийг модулийн түвшинд):
|
|
54
50
|
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
```ts
|
|
52
|
+
import { EidClient, createEidLogin } from "@gerege-systems/eid-mongolia-sdk";
|
|
57
53
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
res.cookie(TX, JSON.stringify({ state: a.state, nonce: a.nonce, codeVerifier: a.codeVerifier }), cookieOpts);
|
|
62
|
-
res.set("Cache-Control", "no-store").redirect(302, a.url);
|
|
54
|
+
const eid = new EidClient({
|
|
55
|
+
credentials: { rpUUID: process.env.EID_RP_UUID!, rpName: "Интернэт банк", apiSecret: process.env.EID_SECRET! },
|
|
56
|
+
trust: { trustAnchorsPem: [process.env.EID_NATIONAL_ROOT_CA_PEM!] },
|
|
63
57
|
});
|
|
64
58
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
59
|
+
export const eidLogin = createEidLogin({
|
|
60
|
+
client: eid,
|
|
61
|
+
callbackUrl: "https://bank.example.mn/auth/eid/callback", // host нь RP-ийн callbackHosts-д; утасны урсгалд заавал
|
|
62
|
+
async onSuccess(id) {
|
|
63
|
+
// id.etsi (PNOMN-…) — хэрэглэгчийг ҮҮГЭЭР таньна; id.givenName/surname (латин), id.person (кирилл, байвал)
|
|
64
|
+
const user = await users.findOrCreateByEtsi(id.etsi);
|
|
65
|
+
const sid = await sessions.create(user.id); // ШИНЭ session (session fixation)
|
|
66
|
+
return {
|
|
67
|
+
redirect: "/dashboard",
|
|
68
|
+
headers: { "Set-Cookie": `app_session=${sid}; Path=/; HttpOnly; Secure; SameSite=Lax` },
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
// store: redisStore, // олон instance / serverless бол (анхдагч — процессын санах ой)
|
|
72
|
+
// rateLimit: (key) => redisLimiter.allow(key), // "start:<ip>", "push:<idCode>"; анхдагч push 3/мин нэг дугаарт
|
|
79
73
|
});
|
|
80
74
|
```
|
|
81
75
|
|
|
82
|
-
Next.js App Router
|
|
83
|
-
|
|
76
|
+
Next.js App Router — `app/auth/eid/[action]/route.ts`:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { eidLogin } from "@/lib/eid";
|
|
80
|
+
export const dynamic = "force-dynamic";
|
|
81
|
+
export const GET = (req: Request) => eidLogin.handle(req);
|
|
82
|
+
export const POST = (req: Request) => eidLogin.handle(req);
|
|
83
|
+
```
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
хэрэглэгчийн tap-аас эхэлсэн redirect гинжид eID аппыг нээнэ.
|
|
85
|
+
Express:
|
|
87
86
|
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
<style>
|
|
94
|
-
.eid-login { display: inline-flex; align-items: center; justify-content: center; gap: .5rem; min-height: 44px;
|
|
95
|
-
padding: 0 1.25rem; border: 1px solid #d0d5dd; border-radius: 6px; background: #fff; color: #111827;
|
|
96
|
-
font: 500 1rem/1 system-ui, sans-serif; text-decoration: none; }
|
|
97
|
-
.eid-login:hover { background: #f5f7fa; }
|
|
98
|
-
.eid-login:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
|
|
99
|
-
</style>
|
|
87
|
+
```ts
|
|
88
|
+
app.use("/auth/eid", express.json(), async (req, res) => {
|
|
89
|
+
const r = await eidLogin.handleRequest({ method: req.method, url: req.originalUrl, headers: req.headers, body: req.body, ip: req.ip });
|
|
90
|
+
res.status(r.status).set(r.headers).send(r.body);
|
|
91
|
+
});
|
|
100
92
|
```
|
|
101
93
|
|
|
102
|
-
|
|
103
|
-
татаж өөрийн хостоос үйлчил). Google/Apple-ийн товч шиг саармаг (цагаан, хүрээтэй) — таны сайтын бусад нэвтрэх
|
|
104
|
-
товчтой зэрэгцэж болно. Жишээ: <https://demo.eidmongolia.mn>.
|
|
94
|
+
**Хөтөч** — Web Component (React/Vue/энгийн HTML аль нь ч):
|
|
105
95
|
|
|
106
|
-
|
|
96
|
+
```html
|
|
97
|
+
<script type="module">import "@gerege-systems/eid-mongolia-sdk/button";</script>
|
|
98
|
+
<eid-login-button start-url="/auth/eid/start" status-url="/auth/eid/status" lang="mn"></eid-login-button>
|
|
99
|
+
<script type="module">
|
|
100
|
+
document.querySelector("eid-login-button").addEventListener("eid-login-success", (e) => {
|
|
101
|
+
// e.detail = { state: "OK", redirect, data } — preventDefault() хийвэл redirect хийхгүй
|
|
102
|
+
});
|
|
103
|
+
</script>
|
|
104
|
+
```
|
|
107
105
|
|
|
108
|
-
|
|
109
|
-
(`
|
|
110
|
-
|
|
111
|
-
|
|
106
|
+
эсвэл `mountEidLoginButton(el, { startUrl, statusUrl, lang: "en", successUrl, onSuccess, onError })`.
|
|
107
|
+
Атрибут: `lang` (`mn` | `en`), `mode` (`auto` анхдагч — утас → Web2App, бусад → QR цонх; `qr`; `app`), `success-url`.
|
|
108
|
+
Үйл явдал: `eid-login-success`, `eid-login-error` (`detail.error`: `USER_REFUSED…`, `VALIDATION`, `EXPIRED` …).
|
|
109
|
+
Дизайн нь eID нэвтрэх хуудсынх (лого, өнгө, light/dark); `--eid-accent`, `--eid-bg` г.м. CSS хувьсагчаар, `::part(button)`-оор
|
|
110
|
+
тохируулна. Гадны хамааралгүй (QR encoder дотроо), цонх нь focus trap, Esc, `aria-live` төлөвтэй.
|
|
112
111
|
|
|
113
112
|
**Аюулгүй байдал.**
|
|
114
113
|
|
|
115
|
-
- `
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
- `
|
|
119
|
-
|
|
120
|
-
`
|
|
121
|
-
|
|
122
|
-
- `
|
|
123
|
-
-
|
|
124
|
-
(`prefersEphemeralWebBrowserSession = false`), Android Custom Tabs. **WebView хориотой.** `redirect_uri` = таны
|
|
125
|
-
https Universal Link / App Link (custom scheme дэмжихгүй). `state` / `nonce` / `codeVerifier` апп-ын санах ойд;
|
|
126
|
-
code-ийг таны backend `client_secret`-ээр солино (`client_secret`-ийг аппад хадгалахгүй).
|
|
114
|
+
- `sessionToken`, `sessionSecret`, `rpChallenge` серверт (store) үлдэнэ; хөтөчид зөвхөн HttpOnly, Secure, SameSite=Lax cookie
|
|
115
|
+
(`<sessionId>.<binding>`, store-д binding-ийн SHA-256). Status ба callback зөвхөн нэвтрэлтийг **эхлүүлсэн хөтөчид** хариулна —
|
|
116
|
+
өөр хөтчид нээгдсэн callback URL (verifier-тэй ч) хүлээн авагдахгүй (login CSRF).
|
|
117
|
+
- `start` POST нь JSON заавал (simple request биш → cross-origin preflight), `Sec-Fetch-Site: cross-site` → 403.
|
|
118
|
+
- `OK` нь зөвхөн `validateAuth` амжилттай үед: QR → `flowType=QR`, push → `Notification`, утас → `Web2App` + callback-ийн
|
|
119
|
+
`userChallengeVerifier`. Web2App session-ийг poll дуусгахгүй (`WAIT_CALLBACK`). `onSuccess` нэг session-д нэг л удаа
|
|
120
|
+
(store-ийн `delete` атомар байх ёстой — Redis `DEL`).
|
|
121
|
+
- `onSuccess`-ийн `data` хөтөчид очно — нууц бүү оруул. Иргэний бүртгэлтэй эсэхийг push алдаагаар задлахгүй (`eid_unavailable`).
|
|
122
|
+
- Олон instance / serverless (Vercel г.м.) дээр анхдагч санах ойн store ажиллахгүй — `EidLoginStore` (`get`/`set`/`delete`)-ийг Redis-ээр.
|
|
127
123
|
|
|
128
124
|
## 2. Нэвтрэлт (push)
|
|
129
125
|
|
|
@@ -428,7 +424,6 @@ OK ирж болзошгүй. Иймд `ResponseValidator`:
|
|
|
428
424
|
| `ApiError` | бусад HTTP алдаа (`.status`, `.body`, серверийн `.code`, `.retryAfterMs`, `.headers`, `.retryable` — ж: 404 `ORG_NOT_FOUND`) |
|
|
429
425
|
| `ResponseTooLargeError` | хариу SDK-ийн хязгаараас их (JSON 4 MiB, PDF `pdfMaxBytes`) — `.op`, `.limit` |
|
|
430
426
|
| `NetworkError` | timeout/сүлжээ (`.op` — таних тэмдэггүй зам, `.timeout`) |
|
|
431
|
-
| `EidOidcError` | «eID-ээр нэвтрэх» (OIDC) — `.code`: `access_denied`, `login_required`, `state_mismatch`, `invalid_grant`, `invalid_id_token`, `server_error` … |
|
|
432
427
|
| `DeviceLinkError` | device-link холбоос угсрах боломжгүй (`deviceLinkBase` https биш, token/secret/lang хэлбэр, төрөлд хэрэгтэй талбар дутуу) |
|
|
433
428
|
|
|
434
429
|
## mTLS (eIDAS qualified орчин)
|
|
@@ -452,9 +447,7 @@ npm test # build + node --test
|
|
|
452
447
|
### Гэрээний шалгалт
|
|
453
448
|
|
|
454
449
|
SDK-ийн дууддаг RP-API зам бүр (`src/contract.ts`) live [`/.well-known/eid`](https://rp.eidmongolia.mn/.well-known/eid)-ийн
|
|
455
|
-
`endpoints`-д байх
|
|
456
|
-
талбарууд) [discovery](https://login.eidmongolia.mn/.well-known/openid-configuration)-тэй таарах ёстой. Discovery-д
|
|
457
|
-
байгаа ч SDK хамраагүй замууд WARN (fail биш). Сүлжээ шаарддаг тул `npm test`-д ордоггүй:
|
|
450
|
+
`endpoints`-д байх ёстой. Discovery-д байгаа ч SDK хамраагүй замууд WARN (fail биш). Сүлжээ шаарддаг тул `npm test`-д ордоггүй:
|
|
458
451
|
|
|
459
452
|
```bash
|
|
460
453
|
npm run test:contract
|