@gerege-systems/eid-mongolia-sdk 0.12.1 → 0.13.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 CHANGED
@@ -40,7 +40,24 @@ native апп дангаараа token endpoint-ийг дуудаж чадахг
40
40
  **Бүртгэл.** `client_id` = таны RP UUID (`relyingPartyUUID`), `client_secret` = RP API secret (`rp_sk_…`).
41
41
  RP-д `AUTH` эрх, OIDC асаалттай, `redirect_uri` (https, ≤ 10) бүртгэлтэй байна — authorize/token-ий `redirect_uri`
42
42
  бүртгэлтэйтэй **тэмдэгт бүрээрээ** таарах ёстой. Иргэний ETSI дугаар (`pnomn` claim) хэрэгтэй бол `PNOMN` эрх
43
- хүсэж, `scope: "openid pnomn"`. Token endpoint-д RP-ийн IP allowlist мөрдөгдөнө; `requireMtls` RP OIDC ашиглахгүй.
43
+ хүсэж, `scope: "openid pnomn"`. Token endpoint-д RP-ийн IP allowlist мөрдөгдөнө.
44
+
45
+ **mTLS-тэй RP (`require_mtls`).** `login.` хост mTLS хийдэггүй тул ийм RP-ийн code солих хүсэлт
46
+ `login.eidmongolia.mn/oauth2/token` дээр `401 invalid_client` авна. Discovery-ийн `mtls_endpoint_aliases.token_endpoint`
47
+ (RFC 8705 §5, `https://rp.eidmongolia.mn/oauth2/token`) руу RP-API-д хэрэглэдэг **ижил client cert**-ээр явуулна:
48
+ `useMtlsEndpointAliases: true` + `dispatcher` (RP-API client-ийнхтэй ижил undici `Agent`). Discovery-д alias байхгүй
49
+ бол `token_endpoint` руу буцна; alias https биш бол `discovery_failed`. mTLS-гүй RP флаг тавихгүй.
50
+
51
+ ```ts
52
+ import { Agent } from "undici";
53
+ const oidc = new EidOidcClient({
54
+ clientId: process.env.EID_RP_UUID!,
55
+ clientSecret: process.env.EID_SECRET!,
56
+ redirectUri: "https://bank.example.mn/auth/eid/callback",
57
+ dispatcher: new Agent({ connect: { cert: clientCertPem, key: clientKeyPem } }), // RP-API-ийн cert
58
+ useMtlsEndpointAliases: true, // token → https://rp.eidmongolia.mn/oauth2/token
59
+ });
60
+ ```
44
61
 
45
62
  ```ts
46
63
  import { EidOidcClient, EidOidcError } from "@gerege-systems/eid-mongolia-sdk";
package/dist/index.cjs CHANGED
@@ -2034,7 +2034,7 @@ var EidOidcClient = class {
2034
2034
  async exchangeCode(code, codeVerifier) {
2035
2035
  const d = await this.discover();
2036
2036
  const basic = Buffer.from(formEncode(this.cfg.clientId) + ":" + formEncode(this.cfg.clientSecret)).toString("base64");
2037
- const res = await this.fetch(d.token_endpoint, {
2037
+ const res = await this.fetch(this.tokenEndpoint(d), {
2038
2038
  method: "POST",
2039
2039
  headers: {
2040
2040
  Authorization: "Basic " + basic,
@@ -2066,6 +2066,16 @@ var EidOidcClient = class {
2066
2066
  }
2067
2067
  return j.id_token;
2068
2068
  }
2069
+ /** Code солих endpoint: `useMtlsEndpointAliases` + alias байвал alias (RFC 8705 §5), эс бөгөөс `token_endpoint`. */
2070
+ tokenEndpoint(d) {
2071
+ if (!this.cfg.useMtlsEndpointAliases) return d.token_endpoint;
2072
+ const alias = d.mtls_endpoint_aliases?.token_endpoint;
2073
+ if (alias === void 0) return d.token_endpoint;
2074
+ if (typeof alias !== "string" || !alias.startsWith("https://")) {
2075
+ throw new EidOidcError("discovery_failed", "OIDC discovery: mtls_endpoint_aliases.token_endpoint \u0431\u0443\u0440\u0443\u0443");
2076
+ }
2077
+ return alias;
2078
+ }
2069
2079
  /**
2070
2080
  * id_token шалгана: JWKS (`kid`, cache; танихгүй kid → нэг удаа дахин татна) ES256 гарын үсэг, `iss`, `aud`
2071
2081
  * (= clientId; олон aud бол `azp`), `exp`/`iat` (±60 сек), `nonce`. Амжилтгүй бол `invalid_id_token`.
@@ -2142,12 +2152,14 @@ var EidOidcClient = class {
2142
2152
  }
2143
2153
  async fetch(url, init) {
2144
2154
  const f = this.cfg.fetchImpl ?? fetch;
2155
+ const req = {
2156
+ ...init,
2157
+ redirect: "error",
2158
+ signal: AbortSignal.timeout(this.cfg.timeoutMs ?? DEFAULT_TIMEOUT_MS2)
2159
+ };
2160
+ if (this.cfg.dispatcher) req.dispatcher = this.cfg.dispatcher;
2145
2161
  try {
2146
- return await f(url, {
2147
- ...init,
2148
- redirect: "error",
2149
- signal: AbortSignal.timeout(this.cfg.timeoutMs ?? DEFAULT_TIMEOUT_MS2)
2150
- });
2162
+ return await f(url, req);
2151
2163
  } catch (e) {
2152
2164
  const err = e;
2153
2165
  if (err.name === "TimeoutError" || err.name === "AbortError") {
package/dist/index.d.cts CHANGED
@@ -965,6 +965,17 @@ interface EidOidcClientConfig {
965
965
  scope?: string;
966
966
  /** HTTP timeout (мс), анхдагч 10000. */
967
967
  timeoutMs?: number;
968
+ /**
969
+ * undici Dispatcher (mTLS client cert) — RP-API client-ийн `dispatcher`-тэй ижил:
970
+ * `new Agent({ connect: { cert, key } })`. Дамжуулсан бол OIDC-ийн бүх fetch-д хэрэглэнэ. Зөвхөн Node орчинд.
971
+ */
972
+ dispatcher?: unknown;
973
+ /**
974
+ * RFC 8705 §5: `true` бол code солих хүсэлт discovery-ийн `mtls_endpoint_aliases.token_endpoint` руу явна
975
+ * (`require_mtls`-тэй RP — `dispatcher`-т RP-ийн client cert заавал). Discovery-д alias байхгүй бол
976
+ * `token_endpoint` руу буцна; alias https биш бол `discovery_failed`. Анхдагч `false`.
977
+ */
978
+ useMtlsEndpointAliases?: boolean;
968
979
  /** fetch орлуулагч (тест). */
969
980
  fetchImpl?: typeof fetch;
970
981
  }
@@ -973,6 +984,8 @@ interface EidOidcDiscovery {
973
984
  authorization_endpoint: string;
974
985
  token_endpoint: string;
975
986
  jwks_uri: string;
987
+ /** RFC 8705 §5 — mTLS-тэй client-ийн endpoint-ууд (ж: `token_endpoint` → `https://rp.eidmongolia.mn/oauth2/token`). */
988
+ mtls_endpoint_aliases?: Record<string, string>;
976
989
  [k: string]: unknown;
977
990
  }
978
991
  interface CreateAuthorizationOptions {
@@ -1050,6 +1063,8 @@ declare class EidOidcClient {
1050
1063
  handleCallback(input: string | URL | URLSearchParams, checks: EidCallbackChecks): Promise<EidCallbackResult>;
1051
1064
  /** `POST token_endpoint` (client_secret_basic, RFC 6749 §2.3.1) → id_token. */
1052
1065
  private exchangeCode;
1066
+ /** Code солих endpoint: `useMtlsEndpointAliases` + alias байвал alias (RFC 8705 §5), эс бөгөөс `token_endpoint`. */
1067
+ private tokenEndpoint;
1053
1068
  /**
1054
1069
  * id_token шалгана: JWKS (`kid`, cache; танихгүй kid → нэг удаа дахин татна) ES256 гарын үсэг, `iss`, `aud`
1055
1070
  * (= clientId; олон aud бол `azp`), `exp`/`iat` (±60 сек), `nonce`. Амжилтгүй бол `invalid_id_token`.
package/dist/index.d.ts CHANGED
@@ -965,6 +965,17 @@ interface EidOidcClientConfig {
965
965
  scope?: string;
966
966
  /** HTTP timeout (мс), анхдагч 10000. */
967
967
  timeoutMs?: number;
968
+ /**
969
+ * undici Dispatcher (mTLS client cert) — RP-API client-ийн `dispatcher`-тэй ижил:
970
+ * `new Agent({ connect: { cert, key } })`. Дамжуулсан бол OIDC-ийн бүх fetch-д хэрэглэнэ. Зөвхөн Node орчинд.
971
+ */
972
+ dispatcher?: unknown;
973
+ /**
974
+ * RFC 8705 §5: `true` бол code солих хүсэлт discovery-ийн `mtls_endpoint_aliases.token_endpoint` руу явна
975
+ * (`require_mtls`-тэй RP — `dispatcher`-т RP-ийн client cert заавал). Discovery-д alias байхгүй бол
976
+ * `token_endpoint` руу буцна; alias https биш бол `discovery_failed`. Анхдагч `false`.
977
+ */
978
+ useMtlsEndpointAliases?: boolean;
968
979
  /** fetch орлуулагч (тест). */
969
980
  fetchImpl?: typeof fetch;
970
981
  }
@@ -973,6 +984,8 @@ interface EidOidcDiscovery {
973
984
  authorization_endpoint: string;
974
985
  token_endpoint: string;
975
986
  jwks_uri: string;
987
+ /** RFC 8705 §5 — mTLS-тэй client-ийн endpoint-ууд (ж: `token_endpoint` → `https://rp.eidmongolia.mn/oauth2/token`). */
988
+ mtls_endpoint_aliases?: Record<string, string>;
976
989
  [k: string]: unknown;
977
990
  }
978
991
  interface CreateAuthorizationOptions {
@@ -1050,6 +1063,8 @@ declare class EidOidcClient {
1050
1063
  handleCallback(input: string | URL | URLSearchParams, checks: EidCallbackChecks): Promise<EidCallbackResult>;
1051
1064
  /** `POST token_endpoint` (client_secret_basic, RFC 6749 §2.3.1) → id_token. */
1052
1065
  private exchangeCode;
1066
+ /** Code солих endpoint: `useMtlsEndpointAliases` + alias байвал alias (RFC 8705 §5), эс бөгөөс `token_endpoint`. */
1067
+ private tokenEndpoint;
1053
1068
  /**
1054
1069
  * id_token шалгана: JWKS (`kid`, cache; танихгүй kid → нэг удаа дахин татна) ES256 гарын үсэг, `iss`, `aud`
1055
1070
  * (= clientId; олон aud бол `azp`), `exp`/`iat` (±60 сек), `nonce`. Амжилтгүй бол `invalid_id_token`.
package/dist/index.js CHANGED
@@ -1809,7 +1809,7 @@ var EidOidcClient = class {
1809
1809
  async exchangeCode(code, codeVerifier) {
1810
1810
  const d = await this.discover();
1811
1811
  const basic = Buffer.from(formEncode(this.cfg.clientId) + ":" + formEncode(this.cfg.clientSecret)).toString("base64");
1812
- const res = await this.fetch(d.token_endpoint, {
1812
+ const res = await this.fetch(this.tokenEndpoint(d), {
1813
1813
  method: "POST",
1814
1814
  headers: {
1815
1815
  Authorization: "Basic " + basic,
@@ -1841,6 +1841,16 @@ var EidOidcClient = class {
1841
1841
  }
1842
1842
  return j.id_token;
1843
1843
  }
1844
+ /** Code солих endpoint: `useMtlsEndpointAliases` + alias байвал alias (RFC 8705 §5), эс бөгөөс `token_endpoint`. */
1845
+ tokenEndpoint(d) {
1846
+ if (!this.cfg.useMtlsEndpointAliases) return d.token_endpoint;
1847
+ const alias = d.mtls_endpoint_aliases?.token_endpoint;
1848
+ if (alias === void 0) return d.token_endpoint;
1849
+ if (typeof alias !== "string" || !alias.startsWith("https://")) {
1850
+ throw new EidOidcError("discovery_failed", "OIDC discovery: mtls_endpoint_aliases.token_endpoint \u0431\u0443\u0440\u0443\u0443");
1851
+ }
1852
+ return alias;
1853
+ }
1844
1854
  /**
1845
1855
  * id_token шалгана: JWKS (`kid`, cache; танихгүй kid → нэг удаа дахин татна) ES256 гарын үсэг, `iss`, `aud`
1846
1856
  * (= clientId; олон aud бол `azp`), `exp`/`iat` (±60 сек), `nonce`. Амжилтгүй бол `invalid_id_token`.
@@ -1917,12 +1927,14 @@ var EidOidcClient = class {
1917
1927
  }
1918
1928
  async fetch(url, init) {
1919
1929
  const f = this.cfg.fetchImpl ?? fetch;
1930
+ const req = {
1931
+ ...init,
1932
+ redirect: "error",
1933
+ signal: AbortSignal.timeout(this.cfg.timeoutMs ?? DEFAULT_TIMEOUT_MS2)
1934
+ };
1935
+ if (this.cfg.dispatcher) req.dispatcher = this.cfg.dispatcher;
1920
1936
  try {
1921
- return await f(url, {
1922
- ...init,
1923
- redirect: "error",
1924
- signal: AbortSignal.timeout(this.cfg.timeoutMs ?? DEFAULT_TIMEOUT_MS2)
1925
- });
1937
+ return await f(url, req);
1926
1938
  } catch (e) {
1927
1939
  const err = e;
1928
1940
  if (err.name === "TimeoutError" || err.name === "AbortError") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gerege-systems/eid-mongolia-sdk",
3
- "version": "0.12.1",
3
+ "version": "0.13.0",
4
4
  "description": "e-ID Mongolia Relying Party SDK — иргэнээр утсаар нь нэвтрэлт ба хууль ёсны цахим гарын үсэг (RP-API v3, Smart-ID нийцтэй).",
5
5
  "license": "MIT",
6
6
  "type": "module",