@iqauth/sdk 2.0.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/LICENSE +21 -0
- package/README.md +287 -0
- package/dist/browser-session.d.mts +12 -0
- package/dist/browser-session.d.ts +12 -0
- package/dist/browser-session.js +1812 -0
- package/dist/browser-session.mjs +28 -0
- package/dist/browser.d.mts +46 -0
- package/dist/browser.d.ts +46 -0
- package/dist/browser.js +768 -0
- package/dist/browser.mjs +47 -0
- package/dist/chunk-5HF3OBNO.mjs +189 -0
- package/dist/chunk-5WFR6Y33.mjs +59 -0
- package/dist/chunk-6I6RM4MN.mjs +51 -0
- package/dist/chunk-73R6BEGO.mjs +176 -0
- package/dist/chunk-E46DKOVI.mjs +632 -0
- package/dist/chunk-JQWYIIIS.mjs +1740 -0
- package/dist/chunk-X3K3WOBR.mjs +64 -0
- package/dist/chunk-Y6FXYEAI.mjs +10 -0
- package/dist/cli/index.d.mts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +581 -0
- package/dist/cli/index.mjs +57 -0
- package/dist/client-C1DXfB8Z.d.mts +911 -0
- package/dist/client-CggvJmmm.d.ts +911 -0
- package/dist/dev-FUTJZSWN.mjs +56 -0
- package/dist/doctor-OHJRZBBT.mjs +89 -0
- package/dist/errors-CDdl24MP.d.mts +52 -0
- package/dist/errors-CDdl24MP.d.ts +52 -0
- package/dist/express-BKAXB5Nl.d.ts +61 -0
- package/dist/express-CpfyYTmw.d.mts +61 -0
- package/dist/express.d.mts +45 -0
- package/dist/express.d.ts +45 -0
- package/dist/express.js +2252 -0
- package/dist/express.mjs +122 -0
- package/dist/fastify.d.mts +23 -0
- package/dist/fastify.d.ts +23 -0
- package/dist/fastify.js +2062 -0
- package/dist/fastify.mjs +118 -0
- package/dist/hono.d.mts +22 -0
- package/dist/hono.d.ts +22 -0
- package/dist/hono.js +2051 -0
- package/dist/hono.mjs +107 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2070 -0
- package/dist/index.mjs +83 -0
- package/dist/init-LLCSQGNL.mjs +198 -0
- package/dist/keys-NLWFAOEM.mjs +63 -0
- package/dist/mobile.d.mts +11 -0
- package/dist/mobile.d.ts +11 -0
- package/dist/mobile.js +1809 -0
- package/dist/mobile.mjs +25 -0
- package/dist/next.d.mts +37 -0
- package/dist/next.d.ts +37 -0
- package/dist/next.js +2078 -0
- package/dist/next.mjs +130 -0
- package/dist/publishableKey-B5DIK81A.d.mts +24 -0
- package/dist/publishableKey-B5DIK81A.d.ts +24 -0
- package/dist/react.d.mts +196 -0
- package/dist/react.d.ts +196 -0
- package/dist/react.js +1457 -0
- package/dist/react.mjs +787 -0
- package/dist/server/handlers.d.mts +96 -0
- package/dist/server/handlers.d.ts +96 -0
- package/dist/server/handlers.js +243 -0
- package/dist/server/handlers.mjs +14 -0
- package/dist/server.d.mts +14 -0
- package/dist/server.d.ts +14 -0
- package/dist/server.js +2195 -0
- package/dist/server.mjs +47 -0
- package/dist/service.d.mts +11 -0
- package/dist/service.d.ts +11 -0
- package/dist/service.js +1809 -0
- package/dist/service.mjs +25 -0
- package/dist/signIn-C8f6qVjD.d.mts +238 -0
- package/dist/signIn-Cy2lbEXb.d.ts +238 -0
- package/dist/types-Cxl3bQHt.d.mts +900 -0
- package/dist/types-Cxl3bQHt.d.ts +900 -0
- package/docs/APP_INTEGRATION_MATRIX.md +59 -0
- package/docs/BROWSER_SESSION_MIGRATION.md +69 -0
- package/docs/FRESH_IMPLEMENTATION_GUIDE.md +188 -0
- package/docs/TARBALL_RELEASE_WORKFLOW.md +98 -0
- package/docs/V1_TO_V2_UPGRADE_GUIDE.md +318 -0
- package/docs/guides/api-keys.md +130 -0
- package/docs/guides/app-registration.md +149 -0
- package/docs/guides/auth-flows.md +168 -0
- package/docs/guides/branding.md +160 -0
- package/docs/guides/entitlements.md +115 -0
- package/docs/guides/entity-hierarchy.md +200 -0
- package/docs/guides/error-handling.md +251 -0
- package/docs/guides/gdpr-compliance.md +123 -0
- package/docs/guides/invitations.md +143 -0
- package/docs/guides/mfa-enrollment.md +170 -0
- package/docs/guides/middleware-reference.md +205 -0
- package/docs/guides/mobile-native.md +110 -0
- package/docs/guides/roles-and-permissions.md +220 -0
- package/docs/guides/scoped-authorization.md +247 -0
- package/docs/guides/server-platform-integration.md +52 -0
- package/docs/guides/service-automation-integration.md +36 -0
- package/docs/guides/session-management.md +97 -0
- package/docs/guides/tenant-management.md +216 -0
- package/docs/guides/token-verification.md +178 -0
- package/docs/guides/user-management.md +184 -0
- package/docs/guides/webhooks.md +136 -0
- package/docs/integration-prompts/README.md +20 -0
- package/docs/integration-prompts/first-party-browser-app.md +29 -0
- package/docs/integration-prompts/install-from-tarball.md +41 -0
- package/docs/integration-prompts/migrate-from-local-packages-source.md +57 -0
- package/docs/integration-prompts/native-mobile-app.md +24 -0
- package/docs/integration-prompts/server-platform-app.md +20 -0
- package/docs/integration-prompts/service-automation-app.md +20 -0
- package/package.json +115 -0
package/dist/service.mjs
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IQAuthClient
|
|
3
|
+
} from "./chunk-JQWYIIIS.mjs";
|
|
4
|
+
import {
|
|
5
|
+
ErrorCodes,
|
|
6
|
+
IQAuthError
|
|
7
|
+
} from "./chunk-6I6RM4MN.mjs";
|
|
8
|
+
import "./chunk-Y6FXYEAI.mjs";
|
|
9
|
+
|
|
10
|
+
// src/service.ts
|
|
11
|
+
var ServiceIQAuthClient = class extends IQAuthClient {
|
|
12
|
+
constructor(config) {
|
|
13
|
+
super({ ...config, environment: "service" });
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
function createServiceClient(config) {
|
|
17
|
+
return new ServiceIQAuthClient(config);
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
ErrorCodes,
|
|
21
|
+
IQAuthClient,
|
|
22
|
+
IQAuthError,
|
|
23
|
+
ServiceIQAuthClient,
|
|
24
|
+
createServiceClient
|
|
25
|
+
};
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { b as ParsedPublishableKey } from './publishableKey-B5DIK81A.mjs';
|
|
2
|
+
import { d as SessionUser, J as JwtClaims } from './types-Cxl3bQHt.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* SessionManager — core browser-side session state.
|
|
6
|
+
*
|
|
7
|
+
* Responsibilities:
|
|
8
|
+
* - Hold the in-memory access token and decoded user claims.
|
|
9
|
+
* - Coordinate token refresh as a single-flight promise (concurrent fetches
|
|
10
|
+
* wait on the same refresh).
|
|
11
|
+
* - Synchronize session state across tabs in the same origin via
|
|
12
|
+
* BroadcastChannel.
|
|
13
|
+
* - Provide an `auth.fetch()` style helper that auto-attaches the access
|
|
14
|
+
* token and retries once on 401/TOKEN_EXPIRED.
|
|
15
|
+
*
|
|
16
|
+
* Storage:
|
|
17
|
+
* - Access token + claims live in memory only.
|
|
18
|
+
* - Refresh token lives in a first-party cookie (`iqauth_rt`). Sent to the
|
|
19
|
+
* refresh endpoint via `credentials: "include"` and as a JSON body.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
type SessionStatus = "loading" | "authenticated" | "unauthenticated";
|
|
23
|
+
/**
|
|
24
|
+
* Pluggable refresh-token storage. Apps that own a backend can pass a
|
|
25
|
+
* delegate that POSTs the refresh token to a server route which sets an
|
|
26
|
+
* httpOnly first-party cookie (the Phase D backend middleware does this
|
|
27
|
+
* automatically). When unset, the SDK falls back to a JS-readable
|
|
28
|
+
* first-party cookie — convenient for browser-only apps but not as resistant
|
|
29
|
+
* to XSS exfiltration.
|
|
30
|
+
*/
|
|
31
|
+
interface RefreshTokenStore {
|
|
32
|
+
read(): string | null | Promise<string | null>;
|
|
33
|
+
write(token: string): void | Promise<void>;
|
|
34
|
+
clear(): void | Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
interface SessionSnapshot {
|
|
37
|
+
status: SessionStatus;
|
|
38
|
+
accessToken: string | null;
|
|
39
|
+
user: SessionUser | null;
|
|
40
|
+
claims: JwtClaims | null;
|
|
41
|
+
tenantId: string | null;
|
|
42
|
+
/** Last error encountered during bootstrap/refresh. Cleared on success. */
|
|
43
|
+
error: {
|
|
44
|
+
code: string;
|
|
45
|
+
message: string;
|
|
46
|
+
} | null;
|
|
47
|
+
/** Monotonically increasing version; bumped on every state change. */
|
|
48
|
+
version: number;
|
|
49
|
+
}
|
|
50
|
+
interface SessionManagerOptions {
|
|
51
|
+
publishableKey: string;
|
|
52
|
+
/**
|
|
53
|
+
* Override the IQAuth issuer URL. Inferred from the publishable key when
|
|
54
|
+
* omitted. Useful for tests or staging shards.
|
|
55
|
+
*/
|
|
56
|
+
issuer?: string;
|
|
57
|
+
/** BroadcastChannel name; defaults to `iqauth.<appId>`. */
|
|
58
|
+
channelName?: string;
|
|
59
|
+
/** When true, proactively refresh ~60s before access token expiry. */
|
|
60
|
+
proactiveRefresh?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Custom fetch implementation. Defaults to the global `fetch`. Tests
|
|
63
|
+
* inject a mock here.
|
|
64
|
+
*/
|
|
65
|
+
fetchImpl?: typeof fetch;
|
|
66
|
+
/** Optional override for the refresh endpoint path. */
|
|
67
|
+
refreshPath?: string;
|
|
68
|
+
/** Optional override for the userinfo endpoint path. */
|
|
69
|
+
userinfoPath?: string;
|
|
70
|
+
/** Set to false to disable cookie writes (refresh token kept in memory). */
|
|
71
|
+
useCookies?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Custom refresh-token storage. Use this to delegate cookie management to
|
|
74
|
+
* the app's backend (so the cookie can be httpOnly). Defaults to a
|
|
75
|
+
* JS-readable first-party cookie.
|
|
76
|
+
*/
|
|
77
|
+
tokenStore?: RefreshTokenStore;
|
|
78
|
+
/**
|
|
79
|
+
* Soft cap (ms) on how long a tab will wait for another tab's in-flight
|
|
80
|
+
* refresh to finish before falling back to its own. Defaults to 4000.
|
|
81
|
+
*/
|
|
82
|
+
crossTabLockTimeoutMs?: number;
|
|
83
|
+
}
|
|
84
|
+
declare class SessionManager {
|
|
85
|
+
private snapshot;
|
|
86
|
+
private listeners;
|
|
87
|
+
private refreshPromise;
|
|
88
|
+
private channel;
|
|
89
|
+
private readonly tabId;
|
|
90
|
+
private readonly fetchImpl;
|
|
91
|
+
private readonly key;
|
|
92
|
+
private readonly issuer;
|
|
93
|
+
private readonly refreshPath;
|
|
94
|
+
private readonly userinfoPath;
|
|
95
|
+
private readonly useCookies;
|
|
96
|
+
private readonly proactiveRefresh;
|
|
97
|
+
private readonly tokenStore;
|
|
98
|
+
private readonly crossTabLockTimeoutMs;
|
|
99
|
+
private proactiveTimer;
|
|
100
|
+
private bootstrapped;
|
|
101
|
+
/** Pending refresh awaited by other tabs after a `refresh:claim` from us. */
|
|
102
|
+
private remoteRefreshWaiters;
|
|
103
|
+
/** Active claims by other tabs (keyed by source tabId). */
|
|
104
|
+
private foreignClaim;
|
|
105
|
+
constructor(options: SessionManagerOptions);
|
|
106
|
+
get publishableKey(): ParsedPublishableKey;
|
|
107
|
+
get appKey(): string;
|
|
108
|
+
get tenantIdFromKey(): string;
|
|
109
|
+
get issuerUrl(): string;
|
|
110
|
+
getSnapshot(): SessionSnapshot;
|
|
111
|
+
subscribe(listener: (s: SessionSnapshot) => void): () => void;
|
|
112
|
+
/**
|
|
113
|
+
* One-time bootstrap: warm the session from the refresh cookie if present.
|
|
114
|
+
* Safe to call multiple times.
|
|
115
|
+
*/
|
|
116
|
+
bootstrap(): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Single-flight token refresh, coordinated across tabs via BroadcastChannel.
|
|
119
|
+
*
|
|
120
|
+
* Per-tab: concurrent callers share the same `refreshPromise`.
|
|
121
|
+
* Cross-tab: a tab that wants to refresh first broadcasts a `refresh:claim`
|
|
122
|
+
* with its tabId + timestamp. If it has already received a competing claim
|
|
123
|
+
* with an earlier timestamp (or lower tabId on tie), it waits for that
|
|
124
|
+
* tab's `refresh:done` message instead of issuing its own HTTP request.
|
|
125
|
+
* This prevents two tabs racing on rotating refresh tokens, which would
|
|
126
|
+
* invalidate the session.
|
|
127
|
+
*/
|
|
128
|
+
refresh(): Promise<boolean>;
|
|
129
|
+
private runRefresh;
|
|
130
|
+
private claimWins;
|
|
131
|
+
private waitForForeignRefresh;
|
|
132
|
+
/**
|
|
133
|
+
* Apply an access token (e.g. fresh from a callback exchange) to the
|
|
134
|
+
* session and notify subscribers and other tabs.
|
|
135
|
+
*/
|
|
136
|
+
applyAccessToken(accessToken: string, refreshToken?: string): void;
|
|
137
|
+
/**
|
|
138
|
+
* Returns a valid access token, refreshing once if it is expired or about
|
|
139
|
+
* to expire. Resolves to `null` if the session can no longer be revived.
|
|
140
|
+
*/
|
|
141
|
+
getToken(): Promise<string | null>;
|
|
142
|
+
/**
|
|
143
|
+
* Browser-safe HTTP wrapper. Attaches the current access token and retries
|
|
144
|
+
* once on 401 (refreshing in between). Rejects with an `IQAuthError` on
|
|
145
|
+
* the second 401 — the caller is then responsible for redirecting to
|
|
146
|
+
* sign-in (typically by letting the unauthenticated state surface through
|
|
147
|
+
* `<SignedOut/>`).
|
|
148
|
+
*/
|
|
149
|
+
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
150
|
+
/**
|
|
151
|
+
* Clear the session locally and broadcast a sign-out to other tabs. Does
|
|
152
|
+
* not call the server — callers (e.g. signOut helper) are responsible for
|
|
153
|
+
* the server-side logout request.
|
|
154
|
+
*/
|
|
155
|
+
signOutLocal(status?: SessionStatus): void;
|
|
156
|
+
destroy(): void;
|
|
157
|
+
private setStatus;
|
|
158
|
+
private setError;
|
|
159
|
+
private update;
|
|
160
|
+
private isTokenExpiringSoon;
|
|
161
|
+
private scheduleProactiveRefresh;
|
|
162
|
+
private broadcast;
|
|
163
|
+
private broadcastEnvelope;
|
|
164
|
+
private onBroadcast;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Sign-in / sign-out / callback helpers that build on top of the
|
|
169
|
+
* SessionManager. These are usable both from React (via the hook helpers in
|
|
170
|
+
* `@iqauth/sdk/react`) and from plain JS / non-React UIs.
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
interface SignInOptions {
|
|
174
|
+
/**
|
|
175
|
+
* Where the user should land after signing in. Defaults to the current
|
|
176
|
+
* `window.location.href`.
|
|
177
|
+
*/
|
|
178
|
+
returnTo?: string;
|
|
179
|
+
/** Path on the IQAuth host that renders the hosted login UI. */
|
|
180
|
+
signInPath?: string;
|
|
181
|
+
/**
|
|
182
|
+
* Where the IQAuth host should redirect the browser back to once login
|
|
183
|
+
* completes. Defaults to `<origin>/auth/callback` and **must** be
|
|
184
|
+
* registered as an allowed redirect URI for the app.
|
|
185
|
+
*/
|
|
186
|
+
redirectUri?: string;
|
|
187
|
+
/** Extra OIDC scopes beyond `openid` to request. */
|
|
188
|
+
scope?: string;
|
|
189
|
+
}
|
|
190
|
+
interface SignOutOptions {
|
|
191
|
+
/** Where to send the user after sign out. Defaults to the current page. */
|
|
192
|
+
returnTo?: string;
|
|
193
|
+
/** Path on the IQAuth host for the logout endpoint. */
|
|
194
|
+
logoutPath?: string;
|
|
195
|
+
/** Skip the network call to IQAuth and just clear the local session. */
|
|
196
|
+
localOnly?: boolean;
|
|
197
|
+
}
|
|
198
|
+
interface CallbackResult {
|
|
199
|
+
ok: boolean;
|
|
200
|
+
returnTo: string;
|
|
201
|
+
error?: string;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Build the hosted sign-in URL with PKCE + state, persist the PKCE record,
|
|
205
|
+
* and return the URL. The caller is responsible for redirecting; for the
|
|
206
|
+
* common case use {@link redirectToSignIn}.
|
|
207
|
+
*/
|
|
208
|
+
declare function buildSignInUrl(manager: SessionManager, opts?: SignInOptions): Promise<string>;
|
|
209
|
+
declare function redirectToSignIn(manager: SessionManager, opts?: SignInOptions): Promise<void>;
|
|
210
|
+
/**
|
|
211
|
+
* Convenience wrapper used by `useAuth().signIn()`. Identical to
|
|
212
|
+
* {@link redirectToSignIn} but accepts the same shape as Clerk's
|
|
213
|
+
* `signIn({ redirectUrl })`.
|
|
214
|
+
*/
|
|
215
|
+
declare function signIn(manager: SessionManager, opts?: SignInOptions): Promise<void>;
|
|
216
|
+
/**
|
|
217
|
+
* Exchange the authorization code from the callback URL for tokens and seed
|
|
218
|
+
* the session manager. Returns a {@link CallbackResult} describing where the
|
|
219
|
+
* caller should navigate next.
|
|
220
|
+
*
|
|
221
|
+
* Typical usage in an SPA route handler:
|
|
222
|
+
* ```tsx
|
|
223
|
+
* const res = await handleAuthCallback(manager);
|
|
224
|
+
* window.location.replace(res.returnTo);
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
declare function handleAuthCallback(manager: SessionManager, options?: {
|
|
228
|
+
url?: string;
|
|
229
|
+
tokenPath?: string;
|
|
230
|
+
fetchImpl?: typeof fetch;
|
|
231
|
+
}): Promise<CallbackResult>;
|
|
232
|
+
/**
|
|
233
|
+
* Clear the local session, ask IQAuth to revoke the refresh token, and
|
|
234
|
+
* optionally redirect.
|
|
235
|
+
*/
|
|
236
|
+
declare function signOut(manager: SessionManager, opts?: SignOutOptions): Promise<void>;
|
|
237
|
+
|
|
238
|
+
export { type CallbackResult as C, SessionManager as S, type SessionSnapshot as a, type SignInOptions as b, type SignOutOptions as c, type SessionManagerOptions as d, type SessionStatus as e, buildSignInUrl as f, signOut as g, handleAuthCallback as h, redirectToSignIn as r, signIn as s };
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { b as ParsedPublishableKey } from './publishableKey-B5DIK81A.js';
|
|
2
|
+
import { d as SessionUser, J as JwtClaims } from './types-Cxl3bQHt.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* SessionManager — core browser-side session state.
|
|
6
|
+
*
|
|
7
|
+
* Responsibilities:
|
|
8
|
+
* - Hold the in-memory access token and decoded user claims.
|
|
9
|
+
* - Coordinate token refresh as a single-flight promise (concurrent fetches
|
|
10
|
+
* wait on the same refresh).
|
|
11
|
+
* - Synchronize session state across tabs in the same origin via
|
|
12
|
+
* BroadcastChannel.
|
|
13
|
+
* - Provide an `auth.fetch()` style helper that auto-attaches the access
|
|
14
|
+
* token and retries once on 401/TOKEN_EXPIRED.
|
|
15
|
+
*
|
|
16
|
+
* Storage:
|
|
17
|
+
* - Access token + claims live in memory only.
|
|
18
|
+
* - Refresh token lives in a first-party cookie (`iqauth_rt`). Sent to the
|
|
19
|
+
* refresh endpoint via `credentials: "include"` and as a JSON body.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
type SessionStatus = "loading" | "authenticated" | "unauthenticated";
|
|
23
|
+
/**
|
|
24
|
+
* Pluggable refresh-token storage. Apps that own a backend can pass a
|
|
25
|
+
* delegate that POSTs the refresh token to a server route which sets an
|
|
26
|
+
* httpOnly first-party cookie (the Phase D backend middleware does this
|
|
27
|
+
* automatically). When unset, the SDK falls back to a JS-readable
|
|
28
|
+
* first-party cookie — convenient for browser-only apps but not as resistant
|
|
29
|
+
* to XSS exfiltration.
|
|
30
|
+
*/
|
|
31
|
+
interface RefreshTokenStore {
|
|
32
|
+
read(): string | null | Promise<string | null>;
|
|
33
|
+
write(token: string): void | Promise<void>;
|
|
34
|
+
clear(): void | Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
interface SessionSnapshot {
|
|
37
|
+
status: SessionStatus;
|
|
38
|
+
accessToken: string | null;
|
|
39
|
+
user: SessionUser | null;
|
|
40
|
+
claims: JwtClaims | null;
|
|
41
|
+
tenantId: string | null;
|
|
42
|
+
/** Last error encountered during bootstrap/refresh. Cleared on success. */
|
|
43
|
+
error: {
|
|
44
|
+
code: string;
|
|
45
|
+
message: string;
|
|
46
|
+
} | null;
|
|
47
|
+
/** Monotonically increasing version; bumped on every state change. */
|
|
48
|
+
version: number;
|
|
49
|
+
}
|
|
50
|
+
interface SessionManagerOptions {
|
|
51
|
+
publishableKey: string;
|
|
52
|
+
/**
|
|
53
|
+
* Override the IQAuth issuer URL. Inferred from the publishable key when
|
|
54
|
+
* omitted. Useful for tests or staging shards.
|
|
55
|
+
*/
|
|
56
|
+
issuer?: string;
|
|
57
|
+
/** BroadcastChannel name; defaults to `iqauth.<appId>`. */
|
|
58
|
+
channelName?: string;
|
|
59
|
+
/** When true, proactively refresh ~60s before access token expiry. */
|
|
60
|
+
proactiveRefresh?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Custom fetch implementation. Defaults to the global `fetch`. Tests
|
|
63
|
+
* inject a mock here.
|
|
64
|
+
*/
|
|
65
|
+
fetchImpl?: typeof fetch;
|
|
66
|
+
/** Optional override for the refresh endpoint path. */
|
|
67
|
+
refreshPath?: string;
|
|
68
|
+
/** Optional override for the userinfo endpoint path. */
|
|
69
|
+
userinfoPath?: string;
|
|
70
|
+
/** Set to false to disable cookie writes (refresh token kept in memory). */
|
|
71
|
+
useCookies?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Custom refresh-token storage. Use this to delegate cookie management to
|
|
74
|
+
* the app's backend (so the cookie can be httpOnly). Defaults to a
|
|
75
|
+
* JS-readable first-party cookie.
|
|
76
|
+
*/
|
|
77
|
+
tokenStore?: RefreshTokenStore;
|
|
78
|
+
/**
|
|
79
|
+
* Soft cap (ms) on how long a tab will wait for another tab's in-flight
|
|
80
|
+
* refresh to finish before falling back to its own. Defaults to 4000.
|
|
81
|
+
*/
|
|
82
|
+
crossTabLockTimeoutMs?: number;
|
|
83
|
+
}
|
|
84
|
+
declare class SessionManager {
|
|
85
|
+
private snapshot;
|
|
86
|
+
private listeners;
|
|
87
|
+
private refreshPromise;
|
|
88
|
+
private channel;
|
|
89
|
+
private readonly tabId;
|
|
90
|
+
private readonly fetchImpl;
|
|
91
|
+
private readonly key;
|
|
92
|
+
private readonly issuer;
|
|
93
|
+
private readonly refreshPath;
|
|
94
|
+
private readonly userinfoPath;
|
|
95
|
+
private readonly useCookies;
|
|
96
|
+
private readonly proactiveRefresh;
|
|
97
|
+
private readonly tokenStore;
|
|
98
|
+
private readonly crossTabLockTimeoutMs;
|
|
99
|
+
private proactiveTimer;
|
|
100
|
+
private bootstrapped;
|
|
101
|
+
/** Pending refresh awaited by other tabs after a `refresh:claim` from us. */
|
|
102
|
+
private remoteRefreshWaiters;
|
|
103
|
+
/** Active claims by other tabs (keyed by source tabId). */
|
|
104
|
+
private foreignClaim;
|
|
105
|
+
constructor(options: SessionManagerOptions);
|
|
106
|
+
get publishableKey(): ParsedPublishableKey;
|
|
107
|
+
get appKey(): string;
|
|
108
|
+
get tenantIdFromKey(): string;
|
|
109
|
+
get issuerUrl(): string;
|
|
110
|
+
getSnapshot(): SessionSnapshot;
|
|
111
|
+
subscribe(listener: (s: SessionSnapshot) => void): () => void;
|
|
112
|
+
/**
|
|
113
|
+
* One-time bootstrap: warm the session from the refresh cookie if present.
|
|
114
|
+
* Safe to call multiple times.
|
|
115
|
+
*/
|
|
116
|
+
bootstrap(): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Single-flight token refresh, coordinated across tabs via BroadcastChannel.
|
|
119
|
+
*
|
|
120
|
+
* Per-tab: concurrent callers share the same `refreshPromise`.
|
|
121
|
+
* Cross-tab: a tab that wants to refresh first broadcasts a `refresh:claim`
|
|
122
|
+
* with its tabId + timestamp. If it has already received a competing claim
|
|
123
|
+
* with an earlier timestamp (or lower tabId on tie), it waits for that
|
|
124
|
+
* tab's `refresh:done` message instead of issuing its own HTTP request.
|
|
125
|
+
* This prevents two tabs racing on rotating refresh tokens, which would
|
|
126
|
+
* invalidate the session.
|
|
127
|
+
*/
|
|
128
|
+
refresh(): Promise<boolean>;
|
|
129
|
+
private runRefresh;
|
|
130
|
+
private claimWins;
|
|
131
|
+
private waitForForeignRefresh;
|
|
132
|
+
/**
|
|
133
|
+
* Apply an access token (e.g. fresh from a callback exchange) to the
|
|
134
|
+
* session and notify subscribers and other tabs.
|
|
135
|
+
*/
|
|
136
|
+
applyAccessToken(accessToken: string, refreshToken?: string): void;
|
|
137
|
+
/**
|
|
138
|
+
* Returns a valid access token, refreshing once if it is expired or about
|
|
139
|
+
* to expire. Resolves to `null` if the session can no longer be revived.
|
|
140
|
+
*/
|
|
141
|
+
getToken(): Promise<string | null>;
|
|
142
|
+
/**
|
|
143
|
+
* Browser-safe HTTP wrapper. Attaches the current access token and retries
|
|
144
|
+
* once on 401 (refreshing in between). Rejects with an `IQAuthError` on
|
|
145
|
+
* the second 401 — the caller is then responsible for redirecting to
|
|
146
|
+
* sign-in (typically by letting the unauthenticated state surface through
|
|
147
|
+
* `<SignedOut/>`).
|
|
148
|
+
*/
|
|
149
|
+
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
150
|
+
/**
|
|
151
|
+
* Clear the session locally and broadcast a sign-out to other tabs. Does
|
|
152
|
+
* not call the server — callers (e.g. signOut helper) are responsible for
|
|
153
|
+
* the server-side logout request.
|
|
154
|
+
*/
|
|
155
|
+
signOutLocal(status?: SessionStatus): void;
|
|
156
|
+
destroy(): void;
|
|
157
|
+
private setStatus;
|
|
158
|
+
private setError;
|
|
159
|
+
private update;
|
|
160
|
+
private isTokenExpiringSoon;
|
|
161
|
+
private scheduleProactiveRefresh;
|
|
162
|
+
private broadcast;
|
|
163
|
+
private broadcastEnvelope;
|
|
164
|
+
private onBroadcast;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Sign-in / sign-out / callback helpers that build on top of the
|
|
169
|
+
* SessionManager. These are usable both from React (via the hook helpers in
|
|
170
|
+
* `@iqauth/sdk/react`) and from plain JS / non-React UIs.
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
interface SignInOptions {
|
|
174
|
+
/**
|
|
175
|
+
* Where the user should land after signing in. Defaults to the current
|
|
176
|
+
* `window.location.href`.
|
|
177
|
+
*/
|
|
178
|
+
returnTo?: string;
|
|
179
|
+
/** Path on the IQAuth host that renders the hosted login UI. */
|
|
180
|
+
signInPath?: string;
|
|
181
|
+
/**
|
|
182
|
+
* Where the IQAuth host should redirect the browser back to once login
|
|
183
|
+
* completes. Defaults to `<origin>/auth/callback` and **must** be
|
|
184
|
+
* registered as an allowed redirect URI for the app.
|
|
185
|
+
*/
|
|
186
|
+
redirectUri?: string;
|
|
187
|
+
/** Extra OIDC scopes beyond `openid` to request. */
|
|
188
|
+
scope?: string;
|
|
189
|
+
}
|
|
190
|
+
interface SignOutOptions {
|
|
191
|
+
/** Where to send the user after sign out. Defaults to the current page. */
|
|
192
|
+
returnTo?: string;
|
|
193
|
+
/** Path on the IQAuth host for the logout endpoint. */
|
|
194
|
+
logoutPath?: string;
|
|
195
|
+
/** Skip the network call to IQAuth and just clear the local session. */
|
|
196
|
+
localOnly?: boolean;
|
|
197
|
+
}
|
|
198
|
+
interface CallbackResult {
|
|
199
|
+
ok: boolean;
|
|
200
|
+
returnTo: string;
|
|
201
|
+
error?: string;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Build the hosted sign-in URL with PKCE + state, persist the PKCE record,
|
|
205
|
+
* and return the URL. The caller is responsible for redirecting; for the
|
|
206
|
+
* common case use {@link redirectToSignIn}.
|
|
207
|
+
*/
|
|
208
|
+
declare function buildSignInUrl(manager: SessionManager, opts?: SignInOptions): Promise<string>;
|
|
209
|
+
declare function redirectToSignIn(manager: SessionManager, opts?: SignInOptions): Promise<void>;
|
|
210
|
+
/**
|
|
211
|
+
* Convenience wrapper used by `useAuth().signIn()`. Identical to
|
|
212
|
+
* {@link redirectToSignIn} but accepts the same shape as Clerk's
|
|
213
|
+
* `signIn({ redirectUrl })`.
|
|
214
|
+
*/
|
|
215
|
+
declare function signIn(manager: SessionManager, opts?: SignInOptions): Promise<void>;
|
|
216
|
+
/**
|
|
217
|
+
* Exchange the authorization code from the callback URL for tokens and seed
|
|
218
|
+
* the session manager. Returns a {@link CallbackResult} describing where the
|
|
219
|
+
* caller should navigate next.
|
|
220
|
+
*
|
|
221
|
+
* Typical usage in an SPA route handler:
|
|
222
|
+
* ```tsx
|
|
223
|
+
* const res = await handleAuthCallback(manager);
|
|
224
|
+
* window.location.replace(res.returnTo);
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
declare function handleAuthCallback(manager: SessionManager, options?: {
|
|
228
|
+
url?: string;
|
|
229
|
+
tokenPath?: string;
|
|
230
|
+
fetchImpl?: typeof fetch;
|
|
231
|
+
}): Promise<CallbackResult>;
|
|
232
|
+
/**
|
|
233
|
+
* Clear the local session, ask IQAuth to revoke the refresh token, and
|
|
234
|
+
* optionally redirect.
|
|
235
|
+
*/
|
|
236
|
+
declare function signOut(manager: SessionManager, opts?: SignOutOptions): Promise<void>;
|
|
237
|
+
|
|
238
|
+
export { type CallbackResult as C, SessionManager as S, type SessionSnapshot as a, type SignInOptions as b, type SignOutOptions as c, type SessionManagerOptions as d, type SessionStatus as e, buildSignInUrl as f, signOut as g, handleAuthCallback as h, redirectToSignIn as r, signIn as s };
|