@iqauth/sdk 2.0.5 → 2.2.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.
Files changed (38) hide show
  1. package/README.md +19 -3
  2. package/dist/browser.d.mts +2 -2
  3. package/dist/browser.d.ts +2 -2
  4. package/dist/browser.js +57 -6
  5. package/dist/browser.mjs +2 -2
  6. package/dist/{chunk-ZESHDJDU.mjs → chunk-D72UL5HL.mjs} +3 -6
  7. package/dist/{chunk-JQRTY5MY.mjs → chunk-M4J6BPK7.mjs} +3 -8
  8. package/dist/chunk-QEJB7WEQ.mjs +119 -0
  9. package/dist/{chunk-S3M2IXCE.mjs → chunk-QZB745C2.mjs} +3 -8
  10. package/dist/cli/index.js +21 -0
  11. package/dist/cli/index.mjs +1 -1
  12. package/dist/{doctor-OHJRZBBT.mjs → doctor-XCI77BQS.mjs} +2 -1
  13. package/dist/express.js +54 -25
  14. package/dist/express.mjs +5 -8
  15. package/dist/fastify.js +53 -19
  16. package/dist/fastify.mjs +4 -5
  17. package/dist/hono.js +53 -19
  18. package/dist/hono.mjs +4 -5
  19. package/dist/index.d.mts +1 -1
  20. package/dist/index.d.ts +1 -1
  21. package/dist/index.js +59 -4
  22. package/dist/index.mjs +4 -2
  23. package/dist/next.js +66 -34
  24. package/dist/next.mjs +6 -9
  25. package/dist/{publishableKey-B5DIK81A.d.mts → publishableKey-BaR0HoAH.d.mts} +10 -1
  26. package/dist/{publishableKey-B5DIK81A.d.ts → publishableKey-BaR0HoAH.d.ts} +10 -1
  27. package/dist/react.d.mts +91 -4
  28. package/dist/react.d.ts +91 -4
  29. package/dist/react.js +466 -162
  30. package/dist/react.mjs +411 -147
  31. package/dist/server/handlers.js +63 -17
  32. package/dist/server/handlers.mjs +3 -2
  33. package/dist/server.js +53 -21
  34. package/dist/server.mjs +3 -3
  35. package/dist/{signIn-VRNzlNyG.d.ts → signIn-BVDTIA_t.d.ts} +1 -1
  36. package/dist/{signIn-CEMdUAwd.d.mts → signIn-D_kP3v-c.d.mts} +1 -1
  37. package/package.json +1 -1
  38. package/dist/chunk-5WFR6Y33.mjs +0 -59
@@ -27,6 +27,17 @@ __export(handlers_exports, {
27
27
  });
28
28
  module.exports = __toCommonJS(handlers_exports);
29
29
 
30
+ // src/errors.ts
31
+ var IQAuthError = class extends Error {
32
+ constructor(code, message, status, raw) {
33
+ super(message);
34
+ this.name = "IQAuthError";
35
+ this.code = code;
36
+ this.status = status;
37
+ this.raw = raw;
38
+ }
39
+ };
40
+
30
41
  // src/publishableKey.ts
31
42
  function b64urlDecode(input) {
32
43
  const pad = input.length % 4 === 0 ? "" : "=".repeat(4 - input.length % 4);
@@ -40,20 +51,60 @@ function b64urlDecode(input) {
40
51
  const { Buffer: Buffer2 } = require("buffer");
41
52
  return Buffer2.from(normalized, "base64").toString("utf8");
42
53
  }
43
- function parsePublishableKey(raw) {
44
- if (typeof raw !== "string") return null;
45
- const m = raw.match(/^pk_(test|live)_([A-Za-z0-9_-]+)$/);
46
- if (!m) return null;
54
+ function isValidIssuerUrl(iss) {
55
+ if (typeof iss !== "string" || iss.length === 0) return false;
56
+ if (!iss.startsWith("http://") && !iss.startsWith("https://")) return false;
47
57
  try {
48
- const json = JSON.parse(b64urlDecode(m[2]));
49
- if (!json || typeof json !== "object") return null;
50
- if (typeof json.iss !== "string" || typeof json.appId !== "string" || typeof json.tenantId !== "string" || typeof json.kid !== "string") {
51
- return null;
52
- }
53
- return { mode: m[1], iss: json.iss, appId: json.appId, tenantId: json.tenantId, kid: json.kid, raw };
58
+ const u = new URL(iss);
59
+ if (u.protocol !== "http:" && u.protocol !== "https:") return false;
60
+ if (!u.hostname) return false;
61
+ return true;
62
+ } catch {
63
+ return false;
64
+ }
65
+ }
66
+ function assertPublishableKey(raw, opts) {
67
+ const ctx = opts?.context ? `${opts.context}: ` : "";
68
+ if (typeof raw !== "string" || raw.length === 0) {
69
+ throw new IQAuthError(
70
+ "CONFIG_INVALID",
71
+ `${ctx}IQAuth publishable key is missing. Set IQAUTH_PUBLISHABLE_KEY (or pass publishableKey) to a pk_test_\u2026 or pk_live_\u2026 value from the IQAuth admin console.`
72
+ );
73
+ }
74
+ const shapeMatch = raw.match(/^pk_(test|live)_([A-Za-z0-9_-]+)$/);
75
+ if (!shapeMatch) {
76
+ throw new IQAuthError(
77
+ "CONFIG_INVALID",
78
+ `${ctx}IQAuth publishable key is malformed (got ${raw.slice(0, 12)}\u2026). Expected pk_test_\u2026 or pk_live_\u2026; regenerate the key from the IQAuth admin console.`
79
+ );
80
+ }
81
+ let decoded;
82
+ try {
83
+ decoded = JSON.parse(b64urlDecode(shapeMatch[2]));
54
84
  } catch {
55
- return null;
85
+ throw new IQAuthError(
86
+ "CONFIG_INVALID",
87
+ `${ctx}IQAuth publishable key payload is not valid base64url JSON. Regenerate the key from the IQAuth admin console.`
88
+ );
89
+ }
90
+ if (!isPublishableKeyPayload(decoded)) {
91
+ throw new IQAuthError(
92
+ "CONFIG_INVALID",
93
+ `${ctx}IQAuth publishable key payload is missing required fields {iss, appId, tenantId, kid}. Regenerate the key from the IQAuth admin console.`
94
+ );
56
95
  }
96
+ if (!isValidIssuerUrl(decoded.iss)) {
97
+ throw new IQAuthError(
98
+ "CONFIG_INVALID",
99
+ `${ctx}IQAuth publishable key encodes an invalid issuer (iss=${JSON.stringify(decoded.iss)}). Expected a fully-qualified URL like "https://auth.example.com" (scheme required). Regenerate the key from the IQAuth admin console, or set IQAUTH_ISSUER to the correct issuer URL as a temporary workaround.`
100
+ );
101
+ }
102
+ return { mode: shapeMatch[1], iss: decoded.iss, appId: decoded.appId, tenantId: decoded.tenantId, kid: decoded.kid, raw };
103
+ }
104
+ function isPublishableKeyPayload(value) {
105
+ if (!value || typeof value !== "object") return false;
106
+ const v = value;
107
+ return typeof v.iss === "string" && typeof v.appId === "string" && typeof v.tenantId === "string" && typeof v.kid === "string";
57
108
  }
58
109
 
59
110
  // src/server/handlers.ts
@@ -76,12 +127,7 @@ function shouldClearCookiesOnFailure(policy, status, errorCode) {
76
127
  var ACCESS_TOKEN_TTL_SECONDS = 60 * 15;
77
128
  var REFRESH_TOKEN_TTL_SECONDS = 60 * 60 * 24 * 30;
78
129
  function resolve(config) {
79
- const parsed = parsePublishableKey(config.publishableKey);
80
- if (!parsed) {
81
- throw new Error(
82
- "@iqauth/sdk: invalid publishable key passed to iqAuth helpers (expected pk_test_\u2026 or pk_live_\u2026)"
83
- );
84
- }
130
+ const parsed = assertPublishableKey(config.publishableKey, { context: "@iqauth/sdk helpers" });
85
131
  const inferredIssuer = parsed.iss.startsWith("http") ? parsed.iss : `https://${parsed.iss}`;
86
132
  return {
87
133
  publishableKey: config.publishableKey,
@@ -3,8 +3,9 @@ import {
3
3
  handleRefresh,
4
4
  handleSignout,
5
5
  serializeCookie
6
- } from "../chunk-JQRTY5MY.mjs";
7
- import "../chunk-5WFR6Y33.mjs";
6
+ } from "../chunk-M4J6BPK7.mjs";
7
+ import "../chunk-QEJB7WEQ.mjs";
8
+ import "../chunk-6I6RM4MN.mjs";
8
9
  import "../chunk-Y6FXYEAI.mjs";
9
10
  export {
10
11
  handleCallback,
package/dist/server.js CHANGED
@@ -1813,20 +1813,60 @@ function b64urlDecode(input) {
1813
1813
  const { Buffer: Buffer2 } = require("buffer");
1814
1814
  return Buffer2.from(normalized, "base64").toString("utf8");
1815
1815
  }
1816
- function parsePublishableKey(raw) {
1817
- if (typeof raw !== "string") return null;
1818
- const m = raw.match(/^pk_(test|live)_([A-Za-z0-9_-]+)$/);
1819
- if (!m) return null;
1816
+ function isValidIssuerUrl(iss) {
1817
+ if (typeof iss !== "string" || iss.length === 0) return false;
1818
+ if (!iss.startsWith("http://") && !iss.startsWith("https://")) return false;
1820
1819
  try {
1821
- const json = JSON.parse(b64urlDecode(m[2]));
1822
- if (!json || typeof json !== "object") return null;
1823
- if (typeof json.iss !== "string" || typeof json.appId !== "string" || typeof json.tenantId !== "string" || typeof json.kid !== "string") {
1824
- return null;
1825
- }
1826
- return { mode: m[1], iss: json.iss, appId: json.appId, tenantId: json.tenantId, kid: json.kid, raw };
1820
+ const u = new URL(iss);
1821
+ if (u.protocol !== "http:" && u.protocol !== "https:") return false;
1822
+ if (!u.hostname) return false;
1823
+ return true;
1827
1824
  } catch {
1828
- return null;
1825
+ return false;
1826
+ }
1827
+ }
1828
+ function assertPublishableKey(raw, opts) {
1829
+ const ctx = opts?.context ? `${opts.context}: ` : "";
1830
+ if (typeof raw !== "string" || raw.length === 0) {
1831
+ throw new IQAuthError(
1832
+ "CONFIG_INVALID",
1833
+ `${ctx}IQAuth publishable key is missing. Set IQAUTH_PUBLISHABLE_KEY (or pass publishableKey) to a pk_test_\u2026 or pk_live_\u2026 value from the IQAuth admin console.`
1834
+ );
1835
+ }
1836
+ const shapeMatch = raw.match(/^pk_(test|live)_([A-Za-z0-9_-]+)$/);
1837
+ if (!shapeMatch) {
1838
+ throw new IQAuthError(
1839
+ "CONFIG_INVALID",
1840
+ `${ctx}IQAuth publishable key is malformed (got ${raw.slice(0, 12)}\u2026). Expected pk_test_\u2026 or pk_live_\u2026; regenerate the key from the IQAuth admin console.`
1841
+ );
1842
+ }
1843
+ let decoded;
1844
+ try {
1845
+ decoded = JSON.parse(b64urlDecode(shapeMatch[2]));
1846
+ } catch {
1847
+ throw new IQAuthError(
1848
+ "CONFIG_INVALID",
1849
+ `${ctx}IQAuth publishable key payload is not valid base64url JSON. Regenerate the key from the IQAuth admin console.`
1850
+ );
1851
+ }
1852
+ if (!isPublishableKeyPayload(decoded)) {
1853
+ throw new IQAuthError(
1854
+ "CONFIG_INVALID",
1855
+ `${ctx}IQAuth publishable key payload is missing required fields {iss, appId, tenantId, kid}. Regenerate the key from the IQAuth admin console.`
1856
+ );
1857
+ }
1858
+ if (!isValidIssuerUrl(decoded.iss)) {
1859
+ throw new IQAuthError(
1860
+ "CONFIG_INVALID",
1861
+ `${ctx}IQAuth publishable key encodes an invalid issuer (iss=${JSON.stringify(decoded.iss)}). Expected a fully-qualified URL like "https://auth.example.com" (scheme required). Regenerate the key from the IQAuth admin console, or set IQAUTH_ISSUER to the correct issuer URL as a temporary workaround.`
1862
+ );
1829
1863
  }
1864
+ return { mode: shapeMatch[1], iss: decoded.iss, appId: decoded.appId, tenantId: decoded.tenantId, kid: decoded.kid, raw };
1865
+ }
1866
+ function isPublishableKeyPayload(value) {
1867
+ if (!value || typeof value !== "object") return false;
1868
+ const v = value;
1869
+ return typeof v.iss === "string" && typeof v.appId === "string" && typeof v.tenantId === "string" && typeof v.kid === "string";
1830
1870
  }
1831
1871
 
1832
1872
  // src/middleware/express.ts
@@ -1865,10 +1905,7 @@ function readCookie(req, name) {
1865
1905
  return void 0;
1866
1906
  }
1867
1907
  function clientFromPublishableKey(opts) {
1868
- const parsed = parsePublishableKey(opts.publishableKey);
1869
- if (!parsed) {
1870
- throw new Error("iqAuthMiddleware: invalid publishable key");
1871
- }
1908
+ const parsed = assertPublishableKey(opts.publishableKey, { context: "iqAuthMiddleware" });
1872
1909
  const issuer = (opts.issuer ?? (parsed.iss.startsWith("http") ? parsed.iss : `https://${parsed.iss}`)).replace(/\/+$/, "");
1873
1910
  return new IQAuthClient({ baseUrl: issuer, environment: "server" });
1874
1911
  }
@@ -2010,12 +2047,7 @@ function shouldClearCookiesOnFailure(policy, status, errorCode) {
2010
2047
  var ACCESS_TOKEN_TTL_SECONDS = 60 * 15;
2011
2048
  var REFRESH_TOKEN_TTL_SECONDS = 60 * 60 * 24 * 30;
2012
2049
  function resolve(config) {
2013
- const parsed = parsePublishableKey(config.publishableKey);
2014
- if (!parsed) {
2015
- throw new Error(
2016
- "@iqauth/sdk: invalid publishable key passed to iqAuth helpers (expected pk_test_\u2026 or pk_live_\u2026)"
2017
- );
2018
- }
2050
+ const parsed = assertPublishableKey(config.publishableKey, { context: "@iqauth/sdk helpers" });
2019
2051
  const inferredIssuer = parsed.iss.startsWith("http") ? parsed.iss : `https://${parsed.iss}`;
2020
2052
  return {
2021
2053
  publishableKey: config.publishableKey,
package/dist/server.mjs CHANGED
@@ -2,14 +2,14 @@ import {
2
2
  DEFAULT_ACCESS_COOKIE,
3
3
  DEFAULT_REFRESH_COOKIE,
4
4
  iqAuthMiddleware
5
- } from "./chunk-ZESHDJDU.mjs";
5
+ } from "./chunk-D72UL5HL.mjs";
6
6
  import {
7
7
  handleCallback,
8
8
  handleRefresh,
9
9
  handleSignout,
10
10
  serializeCookie
11
- } from "./chunk-JQRTY5MY.mjs";
12
- import "./chunk-5WFR6Y33.mjs";
11
+ } from "./chunk-M4J6BPK7.mjs";
12
+ import "./chunk-QEJB7WEQ.mjs";
13
13
  import {
14
14
  IQAuthClient
15
15
  } from "./chunk-MDUHPQMM.mjs";
@@ -1,4 +1,4 @@
1
- import { b as ParsedPublishableKey } from './publishableKey-B5DIK81A.js';
1
+ import { c as ParsedPublishableKey } from './publishableKey-BaR0HoAH.js';
2
2
  import { d as SessionUser, J as JwtClaims } from './types-Cxl3bQHt.js';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { b as ParsedPublishableKey } from './publishableKey-B5DIK81A.mjs';
1
+ import { c as ParsedPublishableKey } from './publishableKey-BaR0HoAH.mjs';
2
2
  import { d as SessionUser, J as JwtClaims } from './types-Cxl3bQHt.mjs';
3
3
 
4
4
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iqauth/sdk",
3
- "version": "2.0.5",
3
+ "version": "2.2.0",
4
4
  "description": "TypeScript SDK for IQAuth — the canonical way for all IQ projects to integrate with IQAuthService",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -1,59 +0,0 @@
1
- import {
2
- __require
3
- } from "./chunk-Y6FXYEAI.mjs";
4
-
5
- // src/publishableKey.ts
6
- function b64urlEncode(input) {
7
- if (typeof btoa === "function") {
8
- const bytes = new TextEncoder().encode(input);
9
- let bin = "";
10
- for (let i = 0; i < bytes.byteLength; i++) bin += String.fromCharCode(bytes[i]);
11
- return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
12
- }
13
- const { Buffer } = __require("buffer");
14
- return Buffer.from(input, "utf8").toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
15
- }
16
- function b64urlDecode(input) {
17
- const pad = input.length % 4 === 0 ? "" : "=".repeat(4 - input.length % 4);
18
- const normalized = input.replace(/-/g, "+").replace(/_/g, "/") + pad;
19
- if (typeof atob === "function") {
20
- const bin = atob(normalized);
21
- const bytes = new Uint8Array(bin.length);
22
- for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
23
- return new TextDecoder().decode(bytes);
24
- }
25
- const { Buffer } = __require("buffer");
26
- return Buffer.from(normalized, "base64").toString("utf8");
27
- }
28
- function encodePublishableKey(mode, payload) {
29
- if (mode !== "test" && mode !== "live") throw new Error(`Invalid mode: ${mode}`);
30
- return `pk_${mode}_${b64urlEncode(JSON.stringify(payload))}`;
31
- }
32
- function parsePublishableKey(raw) {
33
- if (typeof raw !== "string") return null;
34
- const m = raw.match(/^pk_(test|live)_([A-Za-z0-9_-]+)$/);
35
- if (!m) return null;
36
- try {
37
- const json = JSON.parse(b64urlDecode(m[2]));
38
- if (!json || typeof json !== "object") return null;
39
- if (typeof json.iss !== "string" || typeof json.appId !== "string" || typeof json.tenantId !== "string" || typeof json.kid !== "string") {
40
- return null;
41
- }
42
- return { mode: m[1], iss: json.iss, appId: json.appId, tenantId: json.tenantId, kid: json.kid, raw };
43
- } catch {
44
- return null;
45
- }
46
- }
47
- function isPublishableKey(raw) {
48
- return typeof raw === "string" && /^pk_(test|live)_/.test(raw);
49
- }
50
- function isSecretKey(raw) {
51
- return typeof raw === "string" && /^sk_(test|live)_/.test(raw);
52
- }
53
-
54
- export {
55
- encodePublishableKey,
56
- parsePublishableKey,
57
- isPublishableKey,
58
- isSecretKey
59
- };