@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
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
The canonical TypeScript SDK for **IQAuthService** — DispositionIQ's multi-tenant identity and authorization platform. One package covers the React client, the four major Node frameworks (Express, Fastify, Hono, Next.js), native mobile, and headless service automation.
|
|
10
10
|
|
|
11
|
-
> **New in 2.0
|
|
11
|
+
> **New in 2.7.0** — `IQAuthError` now exposes a typed `code` taxonomy (`token_expired`, `jwks_unavailable`, `rate_limited`, …) plus `err.is(code)` / `IQAuthError.isIQAuthError(value)` helpers, and `tokens.verify<T>()` accepts a custom-claims generic so the returned object is fully typed. Both changes are purely additive — existing `catch (e: Error)` and untyped `verify()` callers keep compiling. See [What's new in 2.7.0](#whats-new-in-270).
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -17,6 +17,8 @@ The canonical TypeScript SDK for **IQAuthService** — DispositionIQ's multi-ten
|
|
|
17
17
|
- [Install](#install)
|
|
18
18
|
- [Five-line integration](#five-line-integration)
|
|
19
19
|
- [Pick your environment](#pick-your-environment)
|
|
20
|
+
- [What's new in 2.7.0](#whats-new-in-270)
|
|
21
|
+
- [What's new in 2.6.5](#whats-new-in-265)
|
|
20
22
|
- [What's new in 2.6.2](#whats-new-in-262)
|
|
21
23
|
- [What's new in 2.6.1](#whats-new-in-261)
|
|
22
24
|
- [What's new in 2.0.3](#whats-new-in-203)
|
|
@@ -174,6 +176,121 @@ The SDK is not "one auth model for every environment". The safe pattern depends
|
|
|
174
176
|
|
|
175
177
|
---
|
|
176
178
|
|
|
179
|
+
## What's new in 2.7.0
|
|
180
|
+
|
|
181
|
+
### 1. Typed `IQAuthError` taxonomy
|
|
182
|
+
|
|
183
|
+
Every SDK-originated throw now carries a `code` from a fixed 10-value union,
|
|
184
|
+
so callers can stop string-matching on `err.message` or guessing whether
|
|
185
|
+
`err.code` is upper-snake or lowercase. Two helpers ship alongside it:
|
|
186
|
+
`IQAuthError.isIQAuthError(value)` (instanceof-safe across realms) and
|
|
187
|
+
`err.is(code)` (narrow-friendly).
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
import { IQAuthError, type IQAuthErrorCode } from "@iqauth/sdk";
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
const claims = await client.tokens.verify(token);
|
|
194
|
+
} catch (err) {
|
|
195
|
+
if (IQAuthError.isIQAuthError(err)) {
|
|
196
|
+
if (err.is("token_expired")) return refreshAndRetry();
|
|
197
|
+
if (err.is("jwks_fetch_failed")) return retryAfterBackoff();
|
|
198
|
+
if (err.is("rate_limited")) return showRateLimitToast();
|
|
199
|
+
if (err.is("network")) return showOfflineBanner();
|
|
200
|
+
if (err.is("config_invalid")) throw err; // boot-time misconfig
|
|
201
|
+
}
|
|
202
|
+
throw err;
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
The full union:
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
type IQAuthErrorCode =
|
|
210
|
+
| "token_expired"
|
|
211
|
+
| "token_invalid"
|
|
212
|
+
| "jwks_unavailable"
|
|
213
|
+
| "jwks_fetch_failed"
|
|
214
|
+
| "rate_limited"
|
|
215
|
+
| "network"
|
|
216
|
+
| "config_invalid"
|
|
217
|
+
| "app_not_found"
|
|
218
|
+
| "permission_denied"
|
|
219
|
+
| "unknown";
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Back-compat:** the field is widened to `IQAuthErrorCode | (string & {})`,
|
|
223
|
+
so server-rethrown codes (`TOKEN_REVOKED`, `SESSION_EXPIRED_INACTIVITY`, …)
|
|
224
|
+
still flow through unchanged. The framework adapters (`/express`,
|
|
225
|
+
`/fastify`, `/hono`) map both upper-snake and the new lowercase codes to
|
|
226
|
+
`401`, so this rollout is invisible to existing app code. `IQAuthError`
|
|
227
|
+
also gains a `cause` accessor (alias for the legacy `raw`).
|
|
228
|
+
|
|
229
|
+
See [`docs/error-handling.md`](./docs/error-handling.md) for the full
|
|
230
|
+
recipe book.
|
|
231
|
+
|
|
232
|
+
### 2. `IQAuthClaims<T>` generic on `tokens.verify`
|
|
233
|
+
|
|
234
|
+
`verify()` now accepts a custom-claims generic so your app's bespoke
|
|
235
|
+
claims show up *typed* on the result — no index-signature widening, no
|
|
236
|
+
`as any`:
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
interface MyClaims { plan: "free" | "pro"; orgId: string }
|
|
240
|
+
|
|
241
|
+
const claims = await client.tokens.verify<MyClaims>(token);
|
|
242
|
+
// ^? IQAuthBaseClaims & MyClaims & JwtClaims
|
|
243
|
+
|
|
244
|
+
if (claims.plan === "pro") doProThing(claims.orgId);
|
|
245
|
+
console.log(claims.tenantId, claims.sub); // base claims still typed
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
`IQAuthBaseClaims` is exported separately for callers composing their own
|
|
249
|
+
envelope. `JwtClaims` continues to be exported and remains the return
|
|
250
|
+
type of `tokens.decode()` / `tokens.getClaims()` for back-compat. Calls
|
|
251
|
+
to `verify()` without a generic argument behave exactly as before.
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## What's new in 2.6.5
|
|
256
|
+
|
|
257
|
+
### Server-managed userinfo (`mountUserinfo: true`)
|
|
258
|
+
|
|
259
|
+
The framework adapters can now auto-mount `GET /api/iqauth/me` so
|
|
260
|
+
server-managed integrators don't have to hand-roll a userinfo handler
|
|
261
|
+
that calls `tokens.verify` and shapes a `data.user` / `data.claims`
|
|
262
|
+
envelope.
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
app.use(iqAuth({
|
|
266
|
+
publishableKey: process.env.IQAUTH_PUBLISHABLE_KEY!,
|
|
267
|
+
secretKey: process.env.IQAUTH_SECRET_KEY!,
|
|
268
|
+
mountUserinfo: true,
|
|
269
|
+
// Optional — shallow-merged over the claim-derived SessionUser defaults.
|
|
270
|
+
userinfoEnricher: async (claims, req) => ({
|
|
271
|
+
name: await loadDisplayName(claims.sub),
|
|
272
|
+
}),
|
|
273
|
+
}));
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Returns the documented `UserinfoResponse` envelope —
|
|
277
|
+
`{ success: true, data: { user, claims, tenantId } }` — which is exactly
|
|
278
|
+
the shape the browser SDK's `SessionManager.bootstrap()` already accepts
|
|
279
|
+
(`data.user` is preferred; `claimsToSessionUser(data.claims)` is the
|
|
280
|
+
fallback). The token is read from `Authorization: Bearer …` OR the
|
|
281
|
+
`iqauth_at` cookie; verification reuses a per-issuer cached
|
|
282
|
+
`TokensModule` so JWKS fetches are amortized.
|
|
283
|
+
|
|
284
|
+
Two new framework-neutral exports for integrators who'd rather mount
|
|
285
|
+
their own route but still emit the canonical envelope:
|
|
286
|
+
`buildUserinfoResponse(claims, { enrich? })` and
|
|
287
|
+
`handleUserinfo(config, { accessToken, req? })`. Re-exported from both
|
|
288
|
+
`@iqauth/sdk` and `@iqauth/sdk/server`. See the
|
|
289
|
+
[Server-managed userinfo](#server-managed-userinfo) section below for
|
|
290
|
+
the full reference.
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
177
294
|
## What's new in 2.6.2
|
|
178
295
|
|
|
179
296
|
### Card grows responsively on desktop (no more phone-sized form)
|
|
@@ -381,6 +498,7 @@ app.use("/admin",
|
|
|
381
498
|
| `GET` | `/api/iqauth/callback` | Receives the OIDC redirect, exchanges the code, sets `iqauth_at` + `iqauth_rt`, redirects to `return_to` |
|
|
382
499
|
| `POST` | `/api/iqauth/refresh` | Reads `iqauth_rt`, rotates, sets new cookies. Honors `clearCookiesOnRefreshFailure` |
|
|
383
500
|
| `POST` | `/api/iqauth/signout` | Revokes the refresh token upstream and clears both cookies |
|
|
501
|
+
| `GET` | `/api/iqauth/me` | **Opt-in via `mountUserinfo: true`.** Verifies the access token and returns the documented userinfo envelope. See [Server-managed userinfo](#server-managed-userinfo) |
|
|
384
502
|
|
|
385
503
|
All three set cookies with `HttpOnly; Secure; SameSite=lax; Path=/` by default. Override per-app:
|
|
386
504
|
|
|
@@ -398,6 +516,60 @@ iqAuth({
|
|
|
398
516
|
|
|
399
517
|
---
|
|
400
518
|
|
|
519
|
+
### Server-managed userinfo
|
|
520
|
+
|
|
521
|
+
When you're doing the cookie-managed pattern (browser SDK proxies through
|
|
522
|
+
your own backend), your frontend needs *some* endpoint to learn "who am I"
|
|
523
|
+
on first paint. Before 2.6.5 you had to hand-roll that handler — call
|
|
524
|
+
`tokens.verify`, shape a `data.user` envelope, and remember to read the
|
|
525
|
+
token from either `Authorization: Bearer …` OR the `iqauth_at` cookie.
|
|
526
|
+
|
|
527
|
+
Opt into the auto-mounted route instead:
|
|
528
|
+
|
|
529
|
+
```ts
|
|
530
|
+
app.use(iqAuth({
|
|
531
|
+
publishableKey: process.env.IQAUTH_PUBLISHABLE_KEY!,
|
|
532
|
+
secretKey: process.env.IQAUTH_SECRET_KEY!,
|
|
533
|
+
mountUserinfo: true,
|
|
534
|
+
// Optional — shallow-merged over the claim-derived SessionUser defaults.
|
|
535
|
+
userinfoEnricher: async (claims, req) => ({
|
|
536
|
+
name: await loadDisplayName(claims.sub),
|
|
537
|
+
}),
|
|
538
|
+
}));
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
`GET /api/iqauth/me` returns the documented `UserinfoResponse` envelope:
|
|
542
|
+
|
|
543
|
+
```jsonc
|
|
544
|
+
{
|
|
545
|
+
"success": true,
|
|
546
|
+
"data": {
|
|
547
|
+
"user": { "sub": "...", "email": "...", "name": "...", "tenantId": "...", "roles": [...], "entitlements": [...] },
|
|
548
|
+
"claims": { /* full verified JWT payload */ },
|
|
549
|
+
"tenantId": "ten_..." // or null
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
This is exactly the shape `SessionManager.bootstrap()` already accepts:
|
|
555
|
+
`data.user` is preferred when present, `claimsToSessionUser(data.claims)`
|
|
556
|
+
is the documented fallback. Same option works on Express, Fastify, Hono,
|
|
557
|
+
and the Next.js handler. Token is verified with a per-issuer cached
|
|
558
|
+
`TokensModule` so JWKS fetches are amortized across requests.
|
|
559
|
+
|
|
560
|
+
Want to mount your own route but still emit the canonical envelope? Use
|
|
561
|
+
the framework-neutral helpers:
|
|
562
|
+
|
|
563
|
+
```ts
|
|
564
|
+
import { buildUserinfoResponse, type UserinfoResponse } from "@iqauth/sdk/server";
|
|
565
|
+
|
|
566
|
+
const envelope: UserinfoResponse = await buildUserinfoResponse(verifiedClaims, {
|
|
567
|
+
enrich: (c) => ({ name: lookupName(c.sub) }),
|
|
568
|
+
});
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
---
|
|
572
|
+
|
|
401
573
|
## Token verification without a framework adapter
|
|
402
574
|
|
|
403
575
|
If you're not using Express/Fastify/Hono/Next (custom Node server, AWS Lambda, Cloudflare Worker, etc.):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { I as IQAuthClient } from './client-
|
|
3
|
-
export { E as ErrorCodes, I as IQAuthError } from './errors-
|
|
4
|
-
import './tokens-
|
|
1
|
+
import { I as IQAuthBrowserSessionClientConfig, S as SessionUser } from './types-Bn8O-OEd.mjs';
|
|
2
|
+
import { I as IQAuthClient } from './client-D8L-PaWr.mjs';
|
|
3
|
+
export { E as ErrorCodes, I as IQAuthError } from './errors-Jl1Jtm-6.mjs';
|
|
4
|
+
import './tokens-B06VtvUi.mjs';
|
|
5
5
|
|
|
6
6
|
declare class BrowserSessionIQAuthClient extends IQAuthClient {
|
|
7
7
|
constructor(config: Omit<IQAuthBrowserSessionClientConfig, "environment">);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { I as IQAuthClient } from './client-
|
|
3
|
-
export { E as ErrorCodes, I as IQAuthError } from './errors-
|
|
4
|
-
import './tokens-
|
|
1
|
+
import { I as IQAuthBrowserSessionClientConfig, S as SessionUser } from './types-Bn8O-OEd.js';
|
|
2
|
+
import { I as IQAuthClient } from './client-DkPL0EPZ.js';
|
|
3
|
+
export { E as ErrorCodes, I as IQAuthError } from './errors-Jl1Jtm-6.js';
|
|
4
|
+
import './tokens-9F6ETrzk.js';
|
|
5
5
|
|
|
6
6
|
declare class BrowserSessionIQAuthClient extends IQAuthClient {
|
|
7
7
|
constructor(config: Omit<IQAuthBrowserSessionClientConfig, "environment">);
|