@iqauth/sdk 2.6.4 → 2.8.1
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 +173 -1
- package/dist/browser-session.d.mts +4 -4
- package/dist/browser-session.d.ts +4 -4
- package/dist/browser-session.js +212 -46
- package/dist/browser-session.mjs +3 -3
- package/dist/browser.d.mts +5 -5
- package/dist/browser.d.ts +5 -5
- package/dist/browser.js +293 -34
- package/dist/browser.mjs +5 -5
- package/dist/{chunk-BVV54LPI.mjs → chunk-25SSYDIP.mjs} +10 -4
- package/dist/{chunk-XAWYUPMO.mjs → chunk-4V7FKOTG.mjs} +242 -22
- package/dist/{chunk-6I6RM4MN.mjs → chunk-6PJRLRB4.mjs} +33 -3
- package/dist/{chunk-SL3KRS4W.mjs → chunk-CIJORODR.mjs} +23 -1
- package/dist/{chunk-LIZYFXH7.mjs → chunk-DFWHSDYQ.mjs} +1 -1
- package/dist/chunk-GLXSIGVS.mjs +66 -0
- package/dist/{chunk-DJIBN2N7.mjs → chunk-GN37E64I.mjs} +29 -7
- package/dist/{chunk-WQWBJSSS.mjs → chunk-HVHNYPDC.mjs} +6 -6
- package/dist/chunk-JRDVUWAL.mjs +46 -0
- package/dist/{chunk-UNYDG2L4.mjs → chunk-NUO2I65G.mjs} +56 -23
- package/dist/{chunk-5T7GHBX6.mjs → chunk-TLET552H.mjs} +36 -0
- package/dist/chunk-VYQ3ETCK.mjs +244 -0
- package/dist/{chunk-3JULWS6F.mjs → chunk-WCELYTJ3.mjs} +3 -3
- package/dist/chunk-WHT6WKTY.mjs +3180 -0
- package/dist/{chunk-MKKZULZR.mjs → chunk-WIFG74IK.mjs} +1 -1
- package/dist/chunk-WSH4SW7F.mjs +490 -0
- package/dist/{chunk-W3F4JYGP.mjs → chunk-ZLJPABB7.mjs} +139 -23
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.mjs +2 -2
- package/dist/{client-BNQe3AgF.d.ts → client-D8L-PaWr.d.mts} +59 -6
- package/dist/{client-kYlJFgPv.d.mts → client-DkPL0EPZ.d.ts} +59 -6
- package/dist/{doctor-YYNHNMLD.mjs → doctor-JAFXWU3X.mjs} +2 -2
- package/dist/errors-Jl1Jtm-6.d.mts +107 -0
- package/dist/errors-Jl1Jtm-6.d.ts +107 -0
- package/dist/{express-CHpfa7D_.d.ts → express-Budysq4h.d.ts} +2 -2
- package/dist/{express-B6_1vBYZ.d.mts → express-DDTA3qV1.d.mts} +2 -2
- package/dist/express.d.mts +7 -6
- package/dist/express.d.ts +7 -6
- package/dist/express.js +563 -85
- package/dist/express.mjs +73 -34
- package/dist/fastify.d.mts +10 -0
- package/dist/fastify.d.ts +10 -0
- package/dist/fastify.js +589 -65
- package/dist/fastify.mjs +101 -11
- package/dist/hono.d.mts +10 -0
- package/dist/hono.d.ts +10 -0
- package/dist/hono.js +566 -65
- package/dist/hono.mjs +78 -11
- package/dist/index-Cko-d5po.d.mts +1848 -0
- package/dist/index-RNqwEcmY.d.ts +1848 -0
- package/dist/index.d.mts +56 -8
- package/dist/index.d.ts +56 -8
- package/dist/index.js +694 -75
- package/dist/index.mjs +30 -10
- package/dist/{keys-NLWFAOEM.mjs → keys-6Y776TG2.mjs} +2 -2
- package/dist/locales.d.mts +1 -1
- package/dist/locales.d.ts +1 -1
- package/dist/locales.js +36 -0
- package/dist/locales.mjs +1 -1
- package/dist/mobile.d.mts +77 -7
- package/dist/mobile.d.ts +77 -7
- package/dist/mobile.js +307 -46
- package/dist/mobile.mjs +98 -3
- package/dist/next.d.mts +10 -1
- package/dist/next.d.ts +10 -1
- package/dist/next.js +596 -205
- package/dist/next.mjs +83 -10
- package/dist/{provisioningBridge-88xjOS2n.d.mts → provisioningBridge-BXPMZCLe.d.ts} +30 -2
- package/dist/{provisioningBridge-DnTfzdZK.d.ts → provisioningBridge-IEycmsgb.d.mts} +30 -2
- package/dist/{publishableKey-BaR0HoAH.d.ts → publishableKey-f2kq-rKw.d.mts} +1 -1
- package/dist/{publishableKey-BaR0HoAH.d.mts → publishableKey-f2kq-rKw.d.ts} +1 -1
- package/dist/react-permissions.d.mts +52 -0
- package/dist/react-permissions.d.ts +52 -0
- package/dist/react-permissions.js +239 -0
- package/dist/react-permissions.mjs +98 -0
- package/dist/react.d.mts +9 -1624
- package/dist/react.d.ts +9 -1624
- package/dist/react.js +882 -73
- package/dist/react.mjs +71 -2631
- package/dist/{reverify-4UEJXUS6.mjs → reverify-C64QXKJO.mjs} +2 -2
- package/dist/server/handlers.d.mts +200 -4
- package/dist/server/handlers.d.ts +200 -4
- package/dist/server/handlers.js +530 -16
- package/dist/server/handlers.mjs +14 -3
- package/dist/server.d.mts +171 -8
- package/dist/server.d.ts +171 -8
- package/dist/server.js +579 -61
- package/dist/server.mjs +99 -12
- package/dist/service.d.mts +4 -4
- package/dist/service.d.ts +4 -4
- package/dist/service.js +212 -46
- package/dist/service.mjs +3 -3
- package/dist/{signIn-CiIBTJIh.d.mts → signIn-CReqfXsh.d.mts} +95 -3
- package/dist/{signIn-OCr88Zf8.d.ts → signIn-Cfa1GTpO.d.ts} +95 -3
- package/dist/{signIn-4OKLDEIH.mjs → signIn-SHBW6Z4T.mjs} +1 -1
- package/dist/test.mjs +3 -3
- package/dist/{tokens-DCyzzn8L.d.mts → tokens-9F6ETrzk.d.ts} +9 -2
- package/dist/{tokens-aHiGFr_E.d.ts → tokens-B06VtvUi.d.mts} +9 -2
- package/dist/{types-DZAflmmq.d.mts → types-Bn8O-OEd.d.mts} +164 -11
- package/dist/{types-DZAflmmq.d.ts → types-Bn8O-OEd.d.ts} +164 -11
- package/dist/{types-6bNdxesb.d.ts → types-DnU2LhXR.d.mts} +7 -1
- package/dist/{types-6bNdxesb.d.mts → types-DnU2LhXR.d.ts} +7 -1
- package/dist/webhooks.d.mts +113 -17
- package/dist/webhooks.d.ts +113 -17
- package/dist/webhooks.js +179 -15
- package/dist/webhooks.mjs +7 -1
- package/dist/ws.d.mts +2 -2
- package/dist/ws.d.ts +2 -2
- package/dist/ws.js +80 -30
- package/dist/ws.mjs +4 -4
- package/docs/error-handling.md +101 -0
- package/docs/guides/effective-permissions.md +171 -0
- package/docs/guides/invitations.md +65 -0
- package/package.json +19 -4
- package/dist/chunk-6TDJJER7.mjs +0 -217
- package/dist/chunk-UKZLOHZG.mjs +0 -83
- package/dist/errors-CDdl24MP.d.mts +0 -52
- package/dist/errors-CDdl24MP.d.ts +0 -52
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TokensModule
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NUO2I65G.mjs";
|
|
4
4
|
import {
|
|
5
5
|
IQAuthError
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6PJRLRB4.mjs";
|
|
7
7
|
|
|
8
8
|
// src/modules/auth.ts
|
|
9
9
|
function parseLoginResponse(data, browserSessionMode) {
|
|
@@ -36,17 +36,27 @@ function parseLoginResponse(data, browserSessionMode) {
|
|
|
36
36
|
tenants: data.tenants
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
|
+
if (data.type === "scope_selection" && data.scopeSelectionToken && data.scopes && data.tenantId) {
|
|
40
|
+
return {
|
|
41
|
+
status: "scope_selection",
|
|
42
|
+
scopeSelectionToken: data.scopeSelectionToken,
|
|
43
|
+
tenantId: data.tenantId,
|
|
44
|
+
scopes: data.scopes
|
|
45
|
+
};
|
|
46
|
+
}
|
|
39
47
|
throw new Error("Unexpected login response shape");
|
|
40
48
|
}
|
|
41
49
|
var AuthModule = class {
|
|
42
50
|
constructor(http) {
|
|
43
51
|
this.http = http;
|
|
44
52
|
}
|
|
45
|
-
async login(email, password) {
|
|
53
|
+
async login(email, password, opts) {
|
|
54
|
+
const body = { email, password };
|
|
55
|
+
if (opts?.scopeHint) body.scopeHint = opts.scopeHint;
|
|
46
56
|
const data = await this.http.request(
|
|
47
57
|
"POST",
|
|
48
58
|
"/api/v1/auth/login",
|
|
49
|
-
|
|
59
|
+
body,
|
|
50
60
|
{ skipAutoRefresh: true }
|
|
51
61
|
);
|
|
52
62
|
return parseLoginResponse(data, this.http.isBrowserSession());
|
|
@@ -84,13 +94,29 @@ var AuthModule = class {
|
|
|
84
94
|
method
|
|
85
95
|
}, { skipAutoRefresh: true });
|
|
86
96
|
}
|
|
87
|
-
async selectTenant(tenantSelectionToken, tenantId) {
|
|
97
|
+
async selectTenant(tenantSelectionToken, tenantId, opts) {
|
|
98
|
+
const body = { tenantSelectionToken, tenantId };
|
|
99
|
+
if (opts?.scopeHint) body.scopeHint = opts.scopeHint;
|
|
88
100
|
const data = await this.http.request(
|
|
89
101
|
"POST",
|
|
90
102
|
"/api/v1/auth/select-tenant",
|
|
103
|
+
body,
|
|
104
|
+
{ skipAutoRefresh: true }
|
|
105
|
+
);
|
|
106
|
+
return parseLoginResponse(data, this.http.isBrowserSession());
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Task #171 — redeem a scope-selection token + chosen membership for a
|
|
110
|
+
* real authenticated session. `membershipId` must be one of the scopes
|
|
111
|
+
* returned in the prior `scope_selection` envelope.
|
|
112
|
+
*/
|
|
113
|
+
async selectScope(scopeSelectionToken, membershipId) {
|
|
114
|
+
const data = await this.http.request(
|
|
115
|
+
"POST",
|
|
116
|
+
"/api/v1/auth/select-scope",
|
|
91
117
|
{
|
|
92
|
-
|
|
93
|
-
|
|
118
|
+
scopeSelectionToken,
|
|
119
|
+
membershipId
|
|
94
120
|
},
|
|
95
121
|
{ skipAutoRefresh: true }
|
|
96
122
|
);
|
|
@@ -484,14 +510,14 @@ var OidcModule = class {
|
|
|
484
510
|
*/
|
|
485
511
|
async handleCallback(params) {
|
|
486
512
|
if (!params.state) {
|
|
487
|
-
throw new IQAuthError("
|
|
513
|
+
throw new IQAuthError("config_invalid", "OIDC callback missing state parameter");
|
|
488
514
|
}
|
|
489
515
|
if (!params.code) {
|
|
490
|
-
throw new IQAuthError("
|
|
516
|
+
throw new IQAuthError("config_invalid", "OIDC callback missing code parameter");
|
|
491
517
|
}
|
|
492
518
|
const stored = await this.stateStore.get(params.state);
|
|
493
519
|
if (!stored) {
|
|
494
|
-
throw new IQAuthError("
|
|
520
|
+
throw new IQAuthError("config_invalid", "Unknown or expired OIDC state");
|
|
495
521
|
}
|
|
496
522
|
let tokens;
|
|
497
523
|
try {
|
|
@@ -509,7 +535,7 @@ var OidcModule = class {
|
|
|
509
535
|
if (tokens.id_token) {
|
|
510
536
|
if (!this.tokensModule) {
|
|
511
537
|
throw new IQAuthError(
|
|
512
|
-
"
|
|
538
|
+
"config_invalid",
|
|
513
539
|
"OIDC handleCallback received an id_token but no TokensModule is configured for verification"
|
|
514
540
|
);
|
|
515
541
|
}
|
|
@@ -520,7 +546,7 @@ var OidcModule = class {
|
|
|
520
546
|
const tokenNonce = typeof claimsBag.nonce === "string" ? claimsBag.nonce : void 0;
|
|
521
547
|
if (!tokenNonce || tokenNonce !== stored.nonce) {
|
|
522
548
|
throw new IQAuthError(
|
|
523
|
-
"
|
|
549
|
+
"token_invalid",
|
|
524
550
|
"OIDC id_token nonce did not match the stored value"
|
|
525
551
|
);
|
|
526
552
|
}
|
|
@@ -721,6 +747,9 @@ var AppsModule = class {
|
|
|
721
747
|
* @remarks Wraps GET /api/v1/apps/:appKey
|
|
722
748
|
*/
|
|
723
749
|
async get(appKey) {
|
|
750
|
+
if (typeof appKey !== "string" || appKey.trim() === "") {
|
|
751
|
+
throw new IQAuthError("VALIDATION_ERROR", "appKey is required (no env-var fallback).", 400);
|
|
752
|
+
}
|
|
724
753
|
return this.http.request("GET", `/api/v1/apps/${encodeURIComponent(appKey)}`);
|
|
725
754
|
}
|
|
726
755
|
/**
|
|
@@ -740,6 +769,16 @@ var AppsModule = class {
|
|
|
740
769
|
401
|
|
741
770
|
);
|
|
742
771
|
}
|
|
772
|
+
if (!manifest || typeof manifest.key !== "string" || manifest.key.trim() === "") {
|
|
773
|
+
throw new IQAuthError("VALIDATION_ERROR", "manifest.key (appKey) is required for register().", 400);
|
|
774
|
+
}
|
|
775
|
+
if (!manifest.environment || !["production", "staging", "development"].includes(manifest.environment)) {
|
|
776
|
+
throw new IQAuthError(
|
|
777
|
+
"ENVIRONMENT_REQUIRED",
|
|
778
|
+
"manifest.environment is required and must be 'production', 'staging', or 'development'. This guards against a dev workstation silently overwriting a production app's permission tree.",
|
|
779
|
+
400
|
|
780
|
+
);
|
|
781
|
+
}
|
|
743
782
|
return this.http.request("POST", "/api/v1/apps/sync", manifest);
|
|
744
783
|
}
|
|
745
784
|
/**
|
|
@@ -749,11 +788,14 @@ var AppsModule = class {
|
|
|
749
788
|
* @remarks Uses GET /api/v1/apps/:appKey — catches 404 errors
|
|
750
789
|
*/
|
|
751
790
|
async isRegistered(appKey) {
|
|
791
|
+
if (typeof appKey !== "string" || appKey.trim() === "") {
|
|
792
|
+
throw new IQAuthError("VALIDATION_ERROR", "appKey is required (no env-var fallback).", 400);
|
|
793
|
+
}
|
|
752
794
|
try {
|
|
753
795
|
await this.get(appKey);
|
|
754
796
|
return true;
|
|
755
797
|
} catch (err) {
|
|
756
|
-
if (err.code === "NOT_FOUND" || err.status === 404) {
|
|
798
|
+
if (err.code === "app_not_found" || err.code === "NOT_FOUND" || err.status === 404) {
|
|
757
799
|
return false;
|
|
758
800
|
}
|
|
759
801
|
throw err;
|
|
@@ -790,6 +832,20 @@ var RolesModule = class {
|
|
|
790
832
|
};
|
|
791
833
|
|
|
792
834
|
// src/modules/permissionGroups.ts
|
|
835
|
+
function assertAppKey(appKey, callsite) {
|
|
836
|
+
if (typeof appKey !== "string" || appKey.trim() === "") {
|
|
837
|
+
throw new IQAuthError(
|
|
838
|
+
"VALIDATION_ERROR",
|
|
839
|
+
`appKey is required for ${callsite} (no env-var fallback, no 'product' alias).`,
|
|
840
|
+
400
|
|
841
|
+
);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
function assertNodeKey(nodeKey, callsite) {
|
|
845
|
+
if (typeof nodeKey !== "string" || nodeKey.trim() === "") {
|
|
846
|
+
throw new IQAuthError("VALIDATION_ERROR", `nodeKey is required for ${callsite}.`, 400);
|
|
847
|
+
}
|
|
848
|
+
}
|
|
793
849
|
var PermissionGroupsModule = class {
|
|
794
850
|
constructor(http) {
|
|
795
851
|
this.http = http;
|
|
@@ -810,7 +866,14 @@ var PermissionGroupsModule = class {
|
|
|
810
866
|
return this.http.request("GET", `/api/v1/tenants/${tenantId}/permission-groups/${groupId}/permissions`);
|
|
811
867
|
}
|
|
812
868
|
async addPermission(tenantId, groupId, data) {
|
|
813
|
-
|
|
869
|
+
assertAppKey(data?.appKey, "permissionGroups.addPermission");
|
|
870
|
+
assertNodeKey(data?.nodeKey, "permissionGroups.addPermission");
|
|
871
|
+
return this.http.request("POST", `/api/v1/tenants/${tenantId}/permission-groups/${groupId}/permissions`, {
|
|
872
|
+
appKey: data.appKey,
|
|
873
|
+
nodeKey: data.nodeKey,
|
|
874
|
+
effect: data.effect,
|
|
875
|
+
weight: data.weight
|
|
876
|
+
});
|
|
814
877
|
}
|
|
815
878
|
async removePermission(tenantId, groupId, permissionId) {
|
|
816
879
|
return this.http.request("DELETE", `/api/v1/tenants/${tenantId}/permission-groups/${groupId}/permissions/${permissionId}`);
|
|
@@ -834,21 +897,51 @@ var PermissionGroupsModule = class {
|
|
|
834
897
|
return this.http.request("GET", `/api/v1/tenants/${tenantId}/users/${userId}/permissions/overrides`);
|
|
835
898
|
}
|
|
836
899
|
async addUserOverride(tenantId, userId, data) {
|
|
837
|
-
|
|
900
|
+
assertAppKey(data?.appKey, "permissionGroups.addUserOverride");
|
|
901
|
+
assertNodeKey(data?.nodeKey, "permissionGroups.addUserOverride");
|
|
902
|
+
return this.http.request("POST", `/api/v1/tenants/${tenantId}/users/${userId}/permissions/overrides`, {
|
|
903
|
+
appKey: data.appKey,
|
|
904
|
+
nodeKey: data.nodeKey,
|
|
905
|
+
effect: data.effect,
|
|
906
|
+
weight: data.weight,
|
|
907
|
+
expiresAt: data.expiresAt
|
|
908
|
+
});
|
|
838
909
|
}
|
|
839
910
|
async removeUserOverride(tenantId, userId, overrideId) {
|
|
840
911
|
return this.http.request("DELETE", `/api/v1/tenants/${tenantId}/users/${userId}/permissions/overrides/${overrideId}`);
|
|
841
912
|
}
|
|
913
|
+
/**
|
|
914
|
+
* Task #130 — `appKey` is REQUIRED. The legacy `product` query alias is no
|
|
915
|
+
* longer accepted at the SDK boundary; pass it as `appKey` instead. The
|
|
916
|
+
* server still accepts `product=` from raw HTTP callers during the
|
|
917
|
+
* deprecation window, but the SDK will not silently translate it.
|
|
918
|
+
*/
|
|
842
919
|
async getEffectivePermissions(tenantId, userId, params) {
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
const qs = query.toString();
|
|
847
|
-
return this.http.request("GET", `/api/v1/tenants/${tenantId}/users/${userId}/permissions/effective${qs ? `?${qs}` : ""}`);
|
|
920
|
+
assertAppKey(params?.appKey, "permissionGroups.getEffectivePermissions");
|
|
921
|
+
const qs = new URLSearchParams({ appKey: params.appKey }).toString();
|
|
922
|
+
return this.http.request("GET", `/api/v1/tenants/${tenantId}/users/${userId}/permissions/effective?${qs}`);
|
|
848
923
|
}
|
|
849
924
|
async checkPermission(tenantId, userId, appKey, nodeKey) {
|
|
925
|
+
assertAppKey(appKey, "permissionGroups.checkPermission");
|
|
926
|
+
assertNodeKey(nodeKey, "permissionGroups.checkPermission");
|
|
850
927
|
return this.http.request("POST", `/api/v1/tenants/${tenantId}/users/${userId}/permissions/check`, { appKey, nodeKey });
|
|
851
928
|
}
|
|
929
|
+
/**
|
|
930
|
+
* Task #130 — every entry in `checks` must include a non-empty `appKey`
|
|
931
|
+
* AND `nodeKey`. The SDK validates the whole batch before sending so a
|
|
932
|
+
* single misconfigured entry can't slip through and silently report
|
|
933
|
+
* `allowed: false` from the server's per-entry validation branch.
|
|
934
|
+
*/
|
|
935
|
+
async batchCheckPermissions(tenantId, userId, checks) {
|
|
936
|
+
if (!Array.isArray(checks) || checks.length === 0) {
|
|
937
|
+
throw new IQAuthError("VALIDATION_ERROR", "checks must be a non-empty array of { appKey, nodeKey }.", 400);
|
|
938
|
+
}
|
|
939
|
+
checks.forEach((c, i) => {
|
|
940
|
+
assertAppKey(c?.appKey, `permissionGroups.batchCheckPermissions[${i}]`);
|
|
941
|
+
assertNodeKey(c?.nodeKey, `permissionGroups.batchCheckPermissions[${i}]`);
|
|
942
|
+
});
|
|
943
|
+
return this.http.request("POST", `/api/v1/tenants/${tenantId}/users/${userId}/permissions/batch-check`, { checks });
|
|
944
|
+
}
|
|
852
945
|
};
|
|
853
946
|
|
|
854
947
|
// src/modules/apiKeys.ts
|
|
@@ -1365,7 +1458,7 @@ var HttpClient = class {
|
|
|
1365
1458
|
headers: this.buildHeaders(),
|
|
1366
1459
|
...this.isBrowserSession() ? { credentials: "include" } : (() => {
|
|
1367
1460
|
const refreshToken = this.config.getRefreshToken();
|
|
1368
|
-
if (!refreshToken) throw new IQAuthError("
|
|
1461
|
+
if (!refreshToken) throw new IQAuthError("config_invalid", "No refresh token available");
|
|
1369
1462
|
return { body: JSON.stringify({ refreshToken }) };
|
|
1370
1463
|
})()
|
|
1371
1464
|
});
|
|
@@ -1382,7 +1475,7 @@ var HttpClient = class {
|
|
|
1382
1475
|
return;
|
|
1383
1476
|
}
|
|
1384
1477
|
if (!body.data.accessToken || !body.data.refreshToken) {
|
|
1385
|
-
throw new IQAuthError("
|
|
1478
|
+
throw new IQAuthError("token_invalid", "Refresh response did not include a token pair");
|
|
1386
1479
|
}
|
|
1387
1480
|
const tokens = {
|
|
1388
1481
|
accessToken: body.data.accessToken,
|
|
@@ -1400,7 +1493,7 @@ var HttpClient = class {
|
|
|
1400
1493
|
return this.requestWithRetry(method, path, body, options, false);
|
|
1401
1494
|
}
|
|
1402
1495
|
async requestWithRetry(method, path, body, options, hasRetried) {
|
|
1403
|
-
if (this.config.autoRefresh && !options?.skipAutoRefresh && !this.isBrowserSession() && this.config.getRefreshToken() && this.isTokenExpiringSoon()) {
|
|
1496
|
+
if (this.config.autoRefresh && this.config.proactiveRefresh !== false && !options?.skipAutoRefresh && !this.isBrowserSession() && this.config.getRefreshToken() && this.isTokenExpiringSoon()) {
|
|
1404
1497
|
await this.attemptRefresh();
|
|
1405
1498
|
}
|
|
1406
1499
|
const url = `${this.config.baseUrl}${path}`;
|
|
@@ -1475,6 +1568,10 @@ var IQAuthClient = class _IQAuthClient {
|
|
|
1475
1568
|
this._refreshToken = tokens.refreshToken;
|
|
1476
1569
|
},
|
|
1477
1570
|
autoRefresh: "autoRefresh" in config ? config.autoRefresh !== false : true,
|
|
1571
|
+
// `'app-state'` is mobile-only — on any other environment we treat it
|
|
1572
|
+
// as the default `true` (proactive refresh ON). Only the mobile client
|
|
1573
|
+
// disables proactive refresh and replaces it with an AppState listener.
|
|
1574
|
+
proactiveRefresh: "autoRefresh" in config && config.autoRefresh === "app-state" && _IQAuthClient.resolveEnvironment(config) === "mobile" ? false : true,
|
|
1478
1575
|
onTokenRefresh: "onTokenRefresh" in config ? config.onTokenRefresh : void 0,
|
|
1479
1576
|
sessionHeaderName: config.sessionHeaderName,
|
|
1480
1577
|
sessionHeaderValue: config.sessionHeaderValue,
|
|
@@ -1515,6 +1612,13 @@ var IQAuthClient = class _IQAuthClient {
|
|
|
1515
1612
|
static forServer(config) {
|
|
1516
1613
|
return new _IQAuthClient({ ...config, environment: "server" });
|
|
1517
1614
|
}
|
|
1615
|
+
/**
|
|
1616
|
+
* Construct a mobile-environment client. NOTE: this constructor does NOT
|
|
1617
|
+
* subscribe to React Native's `AppState` even when `autoRefresh: 'app-state'`
|
|
1618
|
+
* is passed — it only disables the per-request proactive refresh. Use
|
|
1619
|
+
* `createMobileClient` from `@iqauth/sdk/mobile` if you want the full
|
|
1620
|
+
* AppState-driven refresh behavior (recommended for Expo / React Native).
|
|
1621
|
+
*/
|
|
1518
1622
|
static forMobile(config) {
|
|
1519
1623
|
return new _IQAuthClient({ ...config, environment: "mobile" });
|
|
1520
1624
|
}
|
|
@@ -1531,6 +1635,18 @@ var IQAuthClient = class _IQAuthClient {
|
|
|
1531
1635
|
getRefreshToken() {
|
|
1532
1636
|
return this._refreshToken;
|
|
1533
1637
|
}
|
|
1638
|
+
/**
|
|
1639
|
+
* Task #126: Eagerly fetch JWKS + OIDC discovery so the first verify() /
|
|
1640
|
+
* refresh round-trip on the request hot path doesn't pay the discovery
|
|
1641
|
+
* fetch latency. Safe to call repeatedly. Errors are swallowed; callers
|
|
1642
|
+
* may fire-and-forget. Called automatically by `iqAuth({...}).attachHelpers()`.
|
|
1643
|
+
*/
|
|
1644
|
+
async prewarm() {
|
|
1645
|
+
await Promise.all([
|
|
1646
|
+
this.tokens.prewarm(),
|
|
1647
|
+
this.oidc.getDiscovery().catch(() => void 0)
|
|
1648
|
+
]);
|
|
1649
|
+
}
|
|
1534
1650
|
getCurrentClaims() {
|
|
1535
1651
|
if (!this._accessToken) return null;
|
|
1536
1652
|
return this.tokens.decode(this._accessToken);
|
package/dist/cli/index.js
CHANGED
|
@@ -538,10 +538,10 @@ async function getCtx(flags) {
|
|
|
538
538
|
const env = await loadEnv(flags.get("env-file") || ".env");
|
|
539
539
|
const baseUrl = flags.get("base-url") || env.IQAUTH_ISSUER;
|
|
540
540
|
const token = flags.get("token") || env.IQAUTH_ADMIN_TOKEN || env.IQAUTH_SECRET_KEY;
|
|
541
|
-
const app = flags.get("app") || env.IQAUTH_APP_ID
|
|
541
|
+
const app = flags.get("app") || env.IQAUTH_APP_ID;
|
|
542
542
|
if (!baseUrl) throw new Error("Missing --base-url (or IQAUTH_ISSUER in env).");
|
|
543
543
|
if (!token) throw new Error("Missing --token (or IQAUTH_ADMIN_TOKEN / IQAUTH_SECRET_KEY in env).");
|
|
544
|
-
if (!app) throw new Error("Missing --app <appId
|
|
544
|
+
if (!app) throw new Error("Missing --app <appId> (or IQAUTH_APP_ID in env). The `IQAUTH_APP_KEY` env-var fallback has been removed (Task #130) \u2014 pass --app explicitly.");
|
|
545
545
|
return { baseUrl, token, app };
|
|
546
546
|
}
|
|
547
547
|
async function runKeys(argv) {
|
package/dist/cli/index.mjs
CHANGED
|
@@ -17,12 +17,12 @@ async function run() {
|
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
case "doctor": {
|
|
20
|
-
const { runDoctor } = await import("../doctor-
|
|
20
|
+
const { runDoctor } = await import("../doctor-JAFXWU3X.mjs");
|
|
21
21
|
await runDoctor(rest);
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
24
|
case "keys": {
|
|
25
|
-
const { runKeys } = await import("../keys-
|
|
25
|
+
const { runKeys } = await import("../keys-6Y776TG2.mjs");
|
|
26
26
|
await runKeys(rest);
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { T as TokensModule } from './tokens-
|
|
1
|
+
import { d as IQAuthEnvironment, T as TokenPair, Y as IQAuthRetryConfig, b1 as ScopeHint, L as LoginResult, b2 as SignupRequest, K as MfaVerifyResult, S as SessionUser, m as Session, U as UserProfile, V as ProvisionUserRequest, W as ProvisionUserResponse, R as UserPermissions, J as JwtClaims, O as OidcDiscovery, y as JwksResponse, z as OidcTokenResponse, b3 as HostedClientContext, n as TenantInfo, C as CreateTenantRequest, o as UpdateTenantRequest, P as PromoteToVendorRequest, p as PromoteToVendorResult, a9 as TenantUser, q as InviteTenantUserRequest, r as InviteTenantUserResult, s as TenantUserRoleUpdate, M as MigrateUserRequest, N as PasswordPolicy, Q as MfaPolicy, B as BrandingConfig, a0 as AppInfo, a1 as PermissionNodeInfo, $ as AppManifest, a2 as AppSyncResult, a3 as Role, a4 as CreateRoleRequest, a5 as UpdateRoleRequest, a6 as AssignRoleRequest, a7 as UserRoleAssignment, aa as PermissionGroup, ab as GroupPermission, ac as AddGroupPermissionRequest, ad as InheritanceRelation, a8 as UserGroupAssignment, ae as UserPermissionOverride, af as AddUserOverrideRequest, ag as EffectivePermission, ah as PermissionCheckResult, aj as CreateApiKeyRequest, ak as CreateApiKeyResult, ai as ApiKeyInfo, al as ApiKeyIntrospection, an as CreateInviteRequest, am as Invitation, ao as InviteValidation, ap as AcceptInviteRequest, ar as CreateWebhookRequest, as as CreateWebhookResult, aq as WebhookEndpoint, at as WebhookDelivery, au as WebhookTestResult, av as Entitlement, aw as GrantEntitlementRequest, ax as Vendor, ay as CreateVendorRequest, az as UpdateVendorRequest, aB as CreateSourceRequest, aA as Source, aC as UpdateSourceRequest, aE as CreateClientRequest, aD as Client, aF as UpdateClientRequest, aG as HierarchyVendor, aJ as HierarchyLink, aN as MembershipWithDetails, aL as CreateMembershipRequest, aK as Membership, aM as UpdateMembershipRequest, aO as AvailableScopesTree, aS as ScopeSwitchResult, aT as GdprExportData, aU as PinStatus, aW as MfaAvailableMethods, aX as TotpEnrollResult, aY as TotpVerifyResult, aZ as SmsEnrollResult, G as MfaEnrollment, a_ as EmailEnrollResult, a$ as BackupCodesResult, b0 as BackupCodeCountResult, t as UpdateBrandingRequest, v as UploadAssetRequest, u as BrandingAsset, w as BrandingDomainMapping, e as IQAuthClientConfig, I as IQAuthBrowserSessionClientConfig, f as IQAuthTokenClientConfig } from './types-Bn8O-OEd.mjs';
|
|
2
|
+
import { T as TokensModule } from './tokens-B06VtvUi.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* SOURCE REFS:
|
|
@@ -18,6 +18,13 @@ interface HttpClientConfig {
|
|
|
18
18
|
getApiKey: () => string | undefined;
|
|
19
19
|
setTokens: (tokens: TokenPair) => void;
|
|
20
20
|
autoRefresh: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* When false, the per-request "expiring soon" proactive refresh is skipped.
|
|
23
|
+
* Reactive refresh on a TOKEN_EXPIRED response still fires when `autoRefresh` is true.
|
|
24
|
+
* Used by the mobile client's `'app-state'` mode where the AppState listener
|
|
25
|
+
* drives proactive refresh instead.
|
|
26
|
+
*/
|
|
27
|
+
proactiveRefresh?: boolean;
|
|
21
28
|
onTokenRefresh?: (tokens: TokenPair) => void;
|
|
22
29
|
sessionHeaderName?: string;
|
|
23
30
|
sessionHeaderValue?: string;
|
|
@@ -49,7 +56,9 @@ declare class HttpClient {
|
|
|
49
56
|
declare class AuthModule {
|
|
50
57
|
private http;
|
|
51
58
|
constructor(http: HttpClient);
|
|
52
|
-
login(email: string, password: string
|
|
59
|
+
login(email: string, password: string, opts?: {
|
|
60
|
+
scopeHint?: ScopeHint;
|
|
61
|
+
}): Promise<LoginResult>;
|
|
53
62
|
signup(input: SignupRequest): Promise<LoginResult>;
|
|
54
63
|
completeMfa(mfaChallengeToken: string, code: string, method?: string): Promise<MfaVerifyResult>;
|
|
55
64
|
completeMfaWithBackup(mfaChallengeToken: string, backupCode: string): Promise<MfaVerifyResult>;
|
|
@@ -57,7 +66,15 @@ declare class AuthModule {
|
|
|
57
66
|
sent: boolean;
|
|
58
67
|
method: string;
|
|
59
68
|
}>;
|
|
60
|
-
selectTenant(tenantSelectionToken: string, tenantId: string
|
|
69
|
+
selectTenant(tenantSelectionToken: string, tenantId: string, opts?: {
|
|
70
|
+
scopeHint?: ScopeHint;
|
|
71
|
+
}): Promise<LoginResult>;
|
|
72
|
+
/**
|
|
73
|
+
* Task #171 — redeem a scope-selection token + chosen membership for a
|
|
74
|
+
* real authenticated session. `membershipId` must be one of the scopes
|
|
75
|
+
* returned in the prior `scope_selection` envelope.
|
|
76
|
+
*/
|
|
77
|
+
selectScope(scopeSelectionToken: string, membershipId: string): Promise<LoginResult>;
|
|
61
78
|
logout(): Promise<{
|
|
62
79
|
message: string;
|
|
63
80
|
}>;
|
|
@@ -594,11 +611,33 @@ declare class PermissionGroupsModule {
|
|
|
594
611
|
removeUserOverride(tenantId: string, userId: string, overrideId: string): Promise<{
|
|
595
612
|
message: string;
|
|
596
613
|
}>;
|
|
614
|
+
/**
|
|
615
|
+
* Task #130 — `appKey` is REQUIRED. The legacy `product` query alias is no
|
|
616
|
+
* longer accepted at the SDK boundary; pass it as `appKey` instead. The
|
|
617
|
+
* server still accepts `product=` from raw HTTP callers during the
|
|
618
|
+
* deprecation window, but the SDK will not silently translate it.
|
|
619
|
+
*/
|
|
597
620
|
getEffectivePermissions(tenantId: string, userId: string, params: {
|
|
598
|
-
|
|
599
|
-
appKey?: string;
|
|
621
|
+
appKey: string;
|
|
600
622
|
}): Promise<EffectivePermission[]>;
|
|
601
623
|
checkPermission(tenantId: string, userId: string, appKey: string, nodeKey: string): Promise<PermissionCheckResult>;
|
|
624
|
+
/**
|
|
625
|
+
* Task #130 — every entry in `checks` must include a non-empty `appKey`
|
|
626
|
+
* AND `nodeKey`. The SDK validates the whole batch before sending so a
|
|
627
|
+
* single misconfigured entry can't slip through and silently report
|
|
628
|
+
* `allowed: false` from the server's per-entry validation branch.
|
|
629
|
+
*/
|
|
630
|
+
batchCheckPermissions(tenantId: string, userId: string, checks: Array<{
|
|
631
|
+
appKey: string;
|
|
632
|
+
nodeKey: string;
|
|
633
|
+
}>): Promise<{
|
|
634
|
+
results: Array<{
|
|
635
|
+
appKey: string;
|
|
636
|
+
nodeKey: string;
|
|
637
|
+
allowed: boolean;
|
|
638
|
+
error?: string;
|
|
639
|
+
}>;
|
|
640
|
+
}>;
|
|
602
641
|
}
|
|
603
642
|
|
|
604
643
|
declare class ApiKeysModule {
|
|
@@ -835,11 +874,25 @@ declare class IQAuthClient {
|
|
|
835
874
|
constructor(config: IQAuthClientConfig);
|
|
836
875
|
static forBrowserSession(config: Omit<IQAuthBrowserSessionClientConfig, "environment">): IQAuthClient;
|
|
837
876
|
static forServer(config: IQAuthTokenClientConfig): IQAuthClient;
|
|
877
|
+
/**
|
|
878
|
+
* Construct a mobile-environment client. NOTE: this constructor does NOT
|
|
879
|
+
* subscribe to React Native's `AppState` even when `autoRefresh: 'app-state'`
|
|
880
|
+
* is passed — it only disables the per-request proactive refresh. Use
|
|
881
|
+
* `createMobileClient` from `@iqauth/sdk/mobile` if you want the full
|
|
882
|
+
* AppState-driven refresh behavior (recommended for Expo / React Native).
|
|
883
|
+
*/
|
|
838
884
|
static forMobile(config: IQAuthTokenClientConfig): IQAuthClient;
|
|
839
885
|
static forService(config: IQAuthTokenClientConfig): IQAuthClient;
|
|
840
886
|
setTokens(tokens: TokenPair): void;
|
|
841
887
|
getAccessToken(): string | undefined;
|
|
842
888
|
getRefreshToken(): string | undefined;
|
|
889
|
+
/**
|
|
890
|
+
* Task #126: Eagerly fetch JWKS + OIDC discovery so the first verify() /
|
|
891
|
+
* refresh round-trip on the request hot path doesn't pay the discovery
|
|
892
|
+
* fetch latency. Safe to call repeatedly. Errors are swallowed; callers
|
|
893
|
+
* may fire-and-forget. Called automatically by `iqAuth({...}).attachHelpers()`.
|
|
894
|
+
*/
|
|
895
|
+
prewarm(): Promise<void>;
|
|
843
896
|
private getCurrentClaims;
|
|
844
897
|
private static resolveEnvironment;
|
|
845
898
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { T as TokensModule } from './tokens-
|
|
1
|
+
import { d as IQAuthEnvironment, T as TokenPair, Y as IQAuthRetryConfig, b1 as ScopeHint, L as LoginResult, b2 as SignupRequest, K as MfaVerifyResult, S as SessionUser, m as Session, U as UserProfile, V as ProvisionUserRequest, W as ProvisionUserResponse, R as UserPermissions, J as JwtClaims, O as OidcDiscovery, y as JwksResponse, z as OidcTokenResponse, b3 as HostedClientContext, n as TenantInfo, C as CreateTenantRequest, o as UpdateTenantRequest, P as PromoteToVendorRequest, p as PromoteToVendorResult, a9 as TenantUser, q as InviteTenantUserRequest, r as InviteTenantUserResult, s as TenantUserRoleUpdate, M as MigrateUserRequest, N as PasswordPolicy, Q as MfaPolicy, B as BrandingConfig, a0 as AppInfo, a1 as PermissionNodeInfo, $ as AppManifest, a2 as AppSyncResult, a3 as Role, a4 as CreateRoleRequest, a5 as UpdateRoleRequest, a6 as AssignRoleRequest, a7 as UserRoleAssignment, aa as PermissionGroup, ab as GroupPermission, ac as AddGroupPermissionRequest, ad as InheritanceRelation, a8 as UserGroupAssignment, ae as UserPermissionOverride, af as AddUserOverrideRequest, ag as EffectivePermission, ah as PermissionCheckResult, aj as CreateApiKeyRequest, ak as CreateApiKeyResult, ai as ApiKeyInfo, al as ApiKeyIntrospection, an as CreateInviteRequest, am as Invitation, ao as InviteValidation, ap as AcceptInviteRequest, ar as CreateWebhookRequest, as as CreateWebhookResult, aq as WebhookEndpoint, at as WebhookDelivery, au as WebhookTestResult, av as Entitlement, aw as GrantEntitlementRequest, ax as Vendor, ay as CreateVendorRequest, az as UpdateVendorRequest, aB as CreateSourceRequest, aA as Source, aC as UpdateSourceRequest, aE as CreateClientRequest, aD as Client, aF as UpdateClientRequest, aG as HierarchyVendor, aJ as HierarchyLink, aN as MembershipWithDetails, aL as CreateMembershipRequest, aK as Membership, aM as UpdateMembershipRequest, aO as AvailableScopesTree, aS as ScopeSwitchResult, aT as GdprExportData, aU as PinStatus, aW as MfaAvailableMethods, aX as TotpEnrollResult, aY as TotpVerifyResult, aZ as SmsEnrollResult, G as MfaEnrollment, a_ as EmailEnrollResult, a$ as BackupCodesResult, b0 as BackupCodeCountResult, t as UpdateBrandingRequest, v as UploadAssetRequest, u as BrandingAsset, w as BrandingDomainMapping, e as IQAuthClientConfig, I as IQAuthBrowserSessionClientConfig, f as IQAuthTokenClientConfig } from './types-Bn8O-OEd.js';
|
|
2
|
+
import { T as TokensModule } from './tokens-9F6ETrzk.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* SOURCE REFS:
|
|
@@ -18,6 +18,13 @@ interface HttpClientConfig {
|
|
|
18
18
|
getApiKey: () => string | undefined;
|
|
19
19
|
setTokens: (tokens: TokenPair) => void;
|
|
20
20
|
autoRefresh: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* When false, the per-request "expiring soon" proactive refresh is skipped.
|
|
23
|
+
* Reactive refresh on a TOKEN_EXPIRED response still fires when `autoRefresh` is true.
|
|
24
|
+
* Used by the mobile client's `'app-state'` mode where the AppState listener
|
|
25
|
+
* drives proactive refresh instead.
|
|
26
|
+
*/
|
|
27
|
+
proactiveRefresh?: boolean;
|
|
21
28
|
onTokenRefresh?: (tokens: TokenPair) => void;
|
|
22
29
|
sessionHeaderName?: string;
|
|
23
30
|
sessionHeaderValue?: string;
|
|
@@ -49,7 +56,9 @@ declare class HttpClient {
|
|
|
49
56
|
declare class AuthModule {
|
|
50
57
|
private http;
|
|
51
58
|
constructor(http: HttpClient);
|
|
52
|
-
login(email: string, password: string
|
|
59
|
+
login(email: string, password: string, opts?: {
|
|
60
|
+
scopeHint?: ScopeHint;
|
|
61
|
+
}): Promise<LoginResult>;
|
|
53
62
|
signup(input: SignupRequest): Promise<LoginResult>;
|
|
54
63
|
completeMfa(mfaChallengeToken: string, code: string, method?: string): Promise<MfaVerifyResult>;
|
|
55
64
|
completeMfaWithBackup(mfaChallengeToken: string, backupCode: string): Promise<MfaVerifyResult>;
|
|
@@ -57,7 +66,15 @@ declare class AuthModule {
|
|
|
57
66
|
sent: boolean;
|
|
58
67
|
method: string;
|
|
59
68
|
}>;
|
|
60
|
-
selectTenant(tenantSelectionToken: string, tenantId: string
|
|
69
|
+
selectTenant(tenantSelectionToken: string, tenantId: string, opts?: {
|
|
70
|
+
scopeHint?: ScopeHint;
|
|
71
|
+
}): Promise<LoginResult>;
|
|
72
|
+
/**
|
|
73
|
+
* Task #171 — redeem a scope-selection token + chosen membership for a
|
|
74
|
+
* real authenticated session. `membershipId` must be one of the scopes
|
|
75
|
+
* returned in the prior `scope_selection` envelope.
|
|
76
|
+
*/
|
|
77
|
+
selectScope(scopeSelectionToken: string, membershipId: string): Promise<LoginResult>;
|
|
61
78
|
logout(): Promise<{
|
|
62
79
|
message: string;
|
|
63
80
|
}>;
|
|
@@ -594,11 +611,33 @@ declare class PermissionGroupsModule {
|
|
|
594
611
|
removeUserOverride(tenantId: string, userId: string, overrideId: string): Promise<{
|
|
595
612
|
message: string;
|
|
596
613
|
}>;
|
|
614
|
+
/**
|
|
615
|
+
* Task #130 — `appKey` is REQUIRED. The legacy `product` query alias is no
|
|
616
|
+
* longer accepted at the SDK boundary; pass it as `appKey` instead. The
|
|
617
|
+
* server still accepts `product=` from raw HTTP callers during the
|
|
618
|
+
* deprecation window, but the SDK will not silently translate it.
|
|
619
|
+
*/
|
|
597
620
|
getEffectivePermissions(tenantId: string, userId: string, params: {
|
|
598
|
-
|
|
599
|
-
appKey?: string;
|
|
621
|
+
appKey: string;
|
|
600
622
|
}): Promise<EffectivePermission[]>;
|
|
601
623
|
checkPermission(tenantId: string, userId: string, appKey: string, nodeKey: string): Promise<PermissionCheckResult>;
|
|
624
|
+
/**
|
|
625
|
+
* Task #130 — every entry in `checks` must include a non-empty `appKey`
|
|
626
|
+
* AND `nodeKey`. The SDK validates the whole batch before sending so a
|
|
627
|
+
* single misconfigured entry can't slip through and silently report
|
|
628
|
+
* `allowed: false` from the server's per-entry validation branch.
|
|
629
|
+
*/
|
|
630
|
+
batchCheckPermissions(tenantId: string, userId: string, checks: Array<{
|
|
631
|
+
appKey: string;
|
|
632
|
+
nodeKey: string;
|
|
633
|
+
}>): Promise<{
|
|
634
|
+
results: Array<{
|
|
635
|
+
appKey: string;
|
|
636
|
+
nodeKey: string;
|
|
637
|
+
allowed: boolean;
|
|
638
|
+
error?: string;
|
|
639
|
+
}>;
|
|
640
|
+
}>;
|
|
602
641
|
}
|
|
603
642
|
|
|
604
643
|
declare class ApiKeysModule {
|
|
@@ -835,11 +874,25 @@ declare class IQAuthClient {
|
|
|
835
874
|
constructor(config: IQAuthClientConfig);
|
|
836
875
|
static forBrowserSession(config: Omit<IQAuthBrowserSessionClientConfig, "environment">): IQAuthClient;
|
|
837
876
|
static forServer(config: IQAuthTokenClientConfig): IQAuthClient;
|
|
877
|
+
/**
|
|
878
|
+
* Construct a mobile-environment client. NOTE: this constructor does NOT
|
|
879
|
+
* subscribe to React Native's `AppState` even when `autoRefresh: 'app-state'`
|
|
880
|
+
* is passed — it only disables the per-request proactive refresh. Use
|
|
881
|
+
* `createMobileClient` from `@iqauth/sdk/mobile` if you want the full
|
|
882
|
+
* AppState-driven refresh behavior (recommended for Expo / React Native).
|
|
883
|
+
*/
|
|
838
884
|
static forMobile(config: IQAuthTokenClientConfig): IQAuthClient;
|
|
839
885
|
static forService(config: IQAuthTokenClientConfig): IQAuthClient;
|
|
840
886
|
setTokens(tokens: TokenPair): void;
|
|
841
887
|
getAccessToken(): string | undefined;
|
|
842
888
|
getRefreshToken(): string | undefined;
|
|
889
|
+
/**
|
|
890
|
+
* Task #126: Eagerly fetch JWKS + OIDC discovery so the first verify() /
|
|
891
|
+
* refresh round-trip on the request hot path doesn't pay the discovery
|
|
892
|
+
* fetch latency. Safe to call repeatedly. Errors are swallowed; callers
|
|
893
|
+
* may fire-and-forget. Called automatically by `iqAuth({...}).attachHelpers()`.
|
|
894
|
+
*/
|
|
895
|
+
prewarm(): Promise<void>;
|
|
843
896
|
private getCurrentClaims;
|
|
844
897
|
private static resolveEnvironment;
|
|
845
898
|
}
|
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
} from "./chunk-X3K3WOBR.mjs";
|
|
6
6
|
import {
|
|
7
7
|
parsePublishableKey
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-HVHNYPDC.mjs";
|
|
9
|
+
import "./chunk-6PJRLRB4.mjs";
|
|
10
10
|
import "./chunk-Y6FXYEAI.mjs";
|
|
11
11
|
|
|
12
12
|
// src/cli/doctor.ts
|