@kiauth/web-sdk 1.0.0 → 1.1.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.
@@ -4,6 +4,71 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.KiauthSDK = factory());
5
5
  })(this, (function () { 'use strict';
6
6
 
7
+ /**
8
+ * Normalizes whatever the backend returned into a complete `KiauthUser`.
9
+ *
10
+ * Why this exists: `/auth/token` and `/auth/verify` historically disagreed on the
11
+ * key name — the login exchange said `verified`, introspection said
12
+ * `kiauth_verified`, and this SDK's type declared only the latter. Any app that
13
+ * wrote `if (user.kiauth_verified)` after a login was reading `undefined` and
14
+ * treating a verified human as unverified.
15
+ *
16
+ * The backend now emits both spellings. This function keeps the SDK correct against
17
+ * older backends too, and guarantees every field is defined rather than silently
18
+ * absent — an `undefined` in a trust decision is worse than a `false`.
19
+ *
20
+ * FAIL CLOSED: anything missing or unrecognised grades as unverified.
21
+ */
22
+ function normalizeUser(raw) {
23
+ const src = raw ?? {};
24
+ // Accept either spelling; require an explicit `true`, never a truthy accident.
25
+ const verified = src.kiauth_verified === true || src.verified === true;
26
+ const assurance = src.assurance_level === 'aadhaar' ||
27
+ src.assurance_level === 'human' ||
28
+ src.assurance_level === 'test' ||
29
+ src.assurance_level === 'none'
30
+ ? src.assurance_level
31
+ : // An older backend sent no grading. A bare `verified: true` cannot be
32
+ // distinguished from a test identity, so do not claim `aadhaar`.
33
+ verified
34
+ ? 'human'
35
+ : 'none';
36
+ const method = src.method === 'aadhaar_okyc' || src.method === 'test_identity' || src.method === 'peer' || src.method === 'none'
37
+ ? src.method
38
+ : 'none';
39
+ const expiresAt = src.verification_expires_at ?? src.verificationExpiry ?? null;
40
+ return {
41
+ name: src.name ?? src.displayName ?? null,
42
+ email: src.email ?? null,
43
+ kiauth_verified: verified,
44
+ verified,
45
+ // Absent on an older backend: fall back to `verified` rather than inventing a
46
+ // durable fact we were not told about.
47
+ identity_verified: src.identity_verified === true || verified,
48
+ assurance_level: assurance,
49
+ method,
50
+ verified_at: src.verified_at ?? null,
51
+ verification_expires_at: expiresAt,
52
+ verificationExpiry: expiresAt,
53
+ assurance_age_days: typeof src.assurance_age_days === 'number' ? src.assurance_age_days : null,
54
+ assurance_fresh: src.assurance_fresh === true,
55
+ // Fail closed: if the backend did not say, assume nothing. A missing flag must
56
+ // not read as "definitely a real human".
57
+ is_test_identity: src.is_test_identity === true,
58
+ uniqueness: 'one_account_per_human',
59
+ userToken: src.userToken ?? ''
60
+ };
61
+ }
62
+ /**
63
+ * The check a production app should make. True only for a real, Aadhaar-verified,
64
+ * non-fabricated human.
65
+ *
66
+ * if (!isProductionTrustworthy(user)) return reject();
67
+ */
68
+ function isProductionTrustworthy(user) {
69
+ return user.kiauth_verified && user.assurance_level === 'aadhaar' && !user.is_test_identity;
70
+ }
71
+
7
72
  class KiauthApi {
8
73
  constructor(config) {
9
74
  this.baseUrl = KiauthApi.resolveBaseUrl(config);
@@ -105,7 +170,10 @@
105
170
  const err = await res.json().catch(() => ({}));
106
171
  throw { code: err.code || 'TOKEN_EXCHANGE_FAILED', message: err.message || 'Failed to exchange authorization code.' };
107
172
  }
108
- return res.json();
173
+ const body = await res.json();
174
+ // Never hand the caller a raw response: normalizeUser guarantees every field is
175
+ // defined, so `user.kiauth_verified` can never be a silent `undefined`.
176
+ return { ...body, user: normalizeUser(body.user) };
109
177
  }
110
178
  async verifyToken(token) {
111
179
  const res = await fetch(`${this.baseUrl}/auth/verify`, {
@@ -119,7 +187,10 @@
119
187
  if (!res.ok) {
120
188
  return { valid: false };
121
189
  }
122
- return res.json();
190
+ const body = await res.json();
191
+ if (!body.valid)
192
+ return { valid: false };
193
+ return { valid: true, user: normalizeUser(body.user) };
123
194
  }
124
195
  async reportSession(clientId, clientSecret, options) {
125
196
  const creds = btoa(`${clientId}:${clientSecret}`);
@@ -3685,6 +3756,14 @@
3685
3756
  this.modal.close();
3686
3757
  }
3687
3758
  }
3759
+ /**
3760
+ * The check a production app should make on every login.
3761
+ *
3762
+ * `user.kiauth_verified` alone is NOT enough — it is also true for Kiauth's test
3763
+ * identities. Exposed as a static so script-tag (UMD) users can reach it too:
3764
+ * if (!KiauthSDK.isProductionTrustworthy(user)) return;
3765
+ */
3766
+ KiauthSDK.isProductionTrustworthy = isProductionTrustworthy;
3688
3767
 
3689
3768
  return KiauthSDK;
3690
3769