@iqauth/sdk 2.1.0 → 2.3.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/README.md +43 -3
- package/dist/browser-session.d.mts +1 -2
- package/dist/browser-session.d.ts +1 -2
- package/dist/browser-session.js +89 -68
- package/dist/browser-session.mjs +2 -1
- package/dist/browser.d.mts +2 -2
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +69 -7
- package/dist/browser.mjs +2 -2
- package/dist/{chunk-ZESHDJDU.mjs → chunk-EKTNEZIH.mjs} +5 -8
- package/dist/{chunk-JQRTY5MY.mjs → chunk-KGEPDXHU.mjs} +12 -8
- package/dist/{chunk-S3M2IXCE.mjs → chunk-RACIPVLD.mjs} +15 -9
- package/dist/chunk-UNYDG2L4.mjs +209 -0
- package/dist/{chunk-MDUHPQMM.mjs → chunk-W3F4JYGP.mjs} +8 -180
- package/dist/chunk-WQWBJSSS.mjs +119 -0
- package/dist/cli/index.js +21 -0
- package/dist/cli/index.mjs +1 -1
- package/dist/{client-DXbHb2ul.d.ts → client-DTX4hNdS.d.ts} +16 -21
- package/dist/{client-Dv4v92Mj.d.mts → client-vdh2a9fJ.d.mts} +16 -21
- package/dist/{doctor-OHJRZBBT.mjs → doctor-A5E7LSFW.mjs} +2 -1
- package/dist/{express-BZmF1llh.d.mts → express-A0-dWEMy.d.mts} +1 -1
- package/dist/{express-B4o3P8vK.d.ts → express-Bo_pJKHN.d.ts} +1 -1
- package/dist/express.d.mts +75 -5
- package/dist/express.d.ts +75 -5
- package/dist/express.js +353 -94
- package/dist/express.mjs +210 -12
- package/dist/fastify.js +153 -88
- package/dist/fastify.mjs +10 -9
- package/dist/hono.js +152 -88
- package/dist/hono.mjs +9 -9
- package/dist/index.d.mts +3 -4
- package/dist/index.d.ts +3 -4
- package/dist/index.js +148 -72
- package/dist/index.mjs +16 -12
- package/dist/mobile.d.mts +1 -2
- package/dist/mobile.d.ts +1 -2
- package/dist/mobile.js +89 -68
- package/dist/mobile.mjs +2 -1
- package/dist/next.d.mts +9 -0
- package/dist/next.d.ts +9 -0
- package/dist/next.js +164 -1649
- package/dist/next.mjs +13 -16
- package/dist/{publishableKey-B5DIK81A.d.mts → publishableKey-BaR0HoAH.d.mts} +10 -1
- package/dist/{publishableKey-B5DIK81A.d.ts → publishableKey-BaR0HoAH.d.ts} +10 -1
- package/dist/react.d.mts +35 -3
- package/dist/react.d.ts +35 -3
- package/dist/react.js +78 -18
- package/dist/react.mjs +14 -2
- package/dist/server/handlers.d.mts +2 -0
- package/dist/server/handlers.d.ts +2 -0
- package/dist/server/handlers.js +72 -17
- package/dist/server/handlers.mjs +3 -2
- package/dist/server.d.mts +2 -3
- package/dist/server.d.ts +2 -3
- package/dist/server.js +151 -89
- package/dist/server.mjs +7 -6
- package/dist/service.d.mts +1 -2
- package/dist/service.d.ts +1 -2
- package/dist/service.js +89 -68
- package/dist/service.mjs +2 -1
- package/dist/{signIn-CEMdUAwd.d.mts → signIn-Cd0P4y9d.d.mts} +9 -1
- package/dist/{signIn-VRNzlNyG.d.ts → signIn-DKakyzeu.d.ts} +9 -1
- package/package.json +3 -2
- package/dist/chunk-5WFR6Y33.mjs +0 -59
package/dist/next.mjs
CHANGED
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
handleRefresh,
|
|
4
4
|
handleSignout,
|
|
5
5
|
serializeCookie
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-KGEPDXHU.mjs";
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
} from "./chunk-
|
|
8
|
+
assertPublishableKey
|
|
9
|
+
} from "./chunk-WQWBJSSS.mjs";
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
} from "./chunk-
|
|
11
|
+
TokensModule
|
|
12
|
+
} from "./chunk-UNYDG2L4.mjs";
|
|
13
13
|
import "./chunk-6I6RM4MN.mjs";
|
|
14
14
|
import "./chunk-Y6FXYEAI.mjs";
|
|
15
15
|
|
|
@@ -35,8 +35,7 @@ function toResponse(hr) {
|
|
|
35
35
|
return new Response(JSON.stringify(hr.body), { status: hr.status, headers });
|
|
36
36
|
}
|
|
37
37
|
function handler(options) {
|
|
38
|
-
const parsed =
|
|
39
|
-
if (!parsed) throw new Error("@iqauth/sdk/next: invalid publishable key");
|
|
38
|
+
const parsed = assertPublishableKey(options.publishableKey, { context: "@iqauth/sdk/next handler" });
|
|
40
39
|
const issuer = (options.issuer ?? (parsed.iss.startsWith("http") ? parsed.iss : `https://${parsed.iss}`)).replace(/\/+$/, "");
|
|
41
40
|
const helperConfig = { ...options, issuer };
|
|
42
41
|
const accessCookie = options.accessCookieName ?? "iqauth_at";
|
|
@@ -60,7 +59,7 @@ function handler(options) {
|
|
|
60
59
|
if (action === "signout") {
|
|
61
60
|
const auth = req.headers.get("authorization");
|
|
62
61
|
const accessToken = auth && auth.replace(/^Bearer /i, "") || readCookieFromHeader(cookieHeader, accessCookie);
|
|
63
|
-
return toResponse(await handleSignout(helperConfig, { accessToken }));
|
|
62
|
+
return toResponse(await handleSignout(helperConfig, { accessToken, ssoCookieHeader: cookieHeader ?? void 0 }));
|
|
64
63
|
}
|
|
65
64
|
return new Response(JSON.stringify({ success: false, error: { code: "NOT_FOUND", message: `Unknown action: ${action}` } }), {
|
|
66
65
|
status: 404,
|
|
@@ -69,11 +68,10 @@ function handler(options) {
|
|
|
69
68
|
};
|
|
70
69
|
}
|
|
71
70
|
function createMiddleware(options) {
|
|
72
|
-
const parsed =
|
|
73
|
-
if (!parsed) throw new Error("@iqauth/sdk/next: invalid publishable key");
|
|
71
|
+
const parsed = assertPublishableKey(options.publishableKey, { context: "@iqauth/sdk/next createMiddleware" });
|
|
74
72
|
const issuer = (options.issuer ?? (parsed.iss.startsWith("http") ? parsed.iss : `https://${parsed.iss}`)).replace(/\/+$/, "");
|
|
75
73
|
const accessCookie = options.accessCookieName ?? "iqauth_at";
|
|
76
|
-
const
|
|
74
|
+
const tokens = new TokensModule(issuer);
|
|
77
75
|
return async (req) => {
|
|
78
76
|
const auth = req.headers.get("authorization");
|
|
79
77
|
let token;
|
|
@@ -86,7 +84,7 @@ function createMiddleware(options) {
|
|
|
86
84
|
});
|
|
87
85
|
}
|
|
88
86
|
try {
|
|
89
|
-
await
|
|
87
|
+
await tokens.verify(token);
|
|
90
88
|
return void 0;
|
|
91
89
|
} catch (err) {
|
|
92
90
|
const code = err.code || "TOKEN_INVALID";
|
|
@@ -98,8 +96,7 @@ function createMiddleware(options) {
|
|
|
98
96
|
};
|
|
99
97
|
}
|
|
100
98
|
async function getAuth(options) {
|
|
101
|
-
const parsed =
|
|
102
|
-
if (!parsed) throw new Error("@iqauth/sdk/next: invalid publishable key");
|
|
99
|
+
const parsed = assertPublishableKey(options.publishableKey, { context: "@iqauth/sdk/next getAuth" });
|
|
103
100
|
const issuer = (options.issuer ?? (parsed.iss.startsWith("http") ? parsed.iss : `https://${parsed.iss}`)).replace(/\/+$/, "");
|
|
104
101
|
const accessCookie = options.accessCookieName ?? "iqauth_at";
|
|
105
102
|
let cookieJar = null;
|
|
@@ -116,9 +113,9 @@ async function getAuth(options) {
|
|
|
116
113
|
}
|
|
117
114
|
const token = cookieJar?.get(accessCookie)?.value;
|
|
118
115
|
if (!token) return null;
|
|
119
|
-
const
|
|
116
|
+
const tokens = new TokensModule(issuer);
|
|
120
117
|
try {
|
|
121
|
-
return await
|
|
118
|
+
return await tokens.verify(token);
|
|
122
119
|
} catch {
|
|
123
120
|
return null;
|
|
124
121
|
}
|
|
@@ -18,7 +18,16 @@ interface ParsedPublishableKey extends PublishableKeyPayload {
|
|
|
18
18
|
}
|
|
19
19
|
declare function encodePublishableKey(mode: KeyMode, payload: PublishableKeyPayload): string;
|
|
20
20
|
declare function parsePublishableKey(raw: string): ParsedPublishableKey | null;
|
|
21
|
+
/**
|
|
22
|
+
* Strict counterpart to `parsePublishableKey` — throws a typed `IQAuthError`
|
|
23
|
+
* (`code: "CONFIG_INVALID"`) with an actionable message when the key is
|
|
24
|
+
* missing, malformed, or encodes a non-URL `iss`. Use this at SDK init so a
|
|
25
|
+
* bad key fails loudly at boot instead of cryptically at first verify.
|
|
26
|
+
*/
|
|
27
|
+
declare function assertPublishableKey(raw: string | undefined | null, opts?: {
|
|
28
|
+
context?: string;
|
|
29
|
+
}): ParsedPublishableKey;
|
|
21
30
|
declare function isPublishableKey(raw: string): boolean;
|
|
22
31
|
declare function isSecretKey(raw: string): boolean;
|
|
23
32
|
|
|
24
|
-
export { type KeyMode as K, type PublishableKeyPayload as P,
|
|
33
|
+
export { type KeyMode as K, type PublishableKeyPayload as P, assertPublishableKey as a, isSecretKey as b, type ParsedPublishableKey as c, encodePublishableKey as e, isPublishableKey as i, parsePublishableKey as p };
|
|
@@ -18,7 +18,16 @@ interface ParsedPublishableKey extends PublishableKeyPayload {
|
|
|
18
18
|
}
|
|
19
19
|
declare function encodePublishableKey(mode: KeyMode, payload: PublishableKeyPayload): string;
|
|
20
20
|
declare function parsePublishableKey(raw: string): ParsedPublishableKey | null;
|
|
21
|
+
/**
|
|
22
|
+
* Strict counterpart to `parsePublishableKey` — throws a typed `IQAuthError`
|
|
23
|
+
* (`code: "CONFIG_INVALID"`) with an actionable message when the key is
|
|
24
|
+
* missing, malformed, or encodes a non-URL `iss`. Use this at SDK init so a
|
|
25
|
+
* bad key fails loudly at boot instead of cryptically at first verify.
|
|
26
|
+
*/
|
|
27
|
+
declare function assertPublishableKey(raw: string | undefined | null, opts?: {
|
|
28
|
+
context?: string;
|
|
29
|
+
}): ParsedPublishableKey;
|
|
21
30
|
declare function isPublishableKey(raw: string): boolean;
|
|
22
31
|
declare function isSecretKey(raw: string): boolean;
|
|
23
32
|
|
|
24
|
-
export { type KeyMode as K, type PublishableKeyPayload as P,
|
|
33
|
+
export { type KeyMode as K, type PublishableKeyPayload as P, assertPublishableKey as a, isSecretKey as b, type ParsedPublishableKey as c, encodePublishableKey as e, isPublishableKey as i, parsePublishableKey as p };
|
package/dist/react.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
|
-
import { S as SessionManager, a as SessionSnapshot, b as SignInOptions, c as SignOutOptions, C as CallbackResult } from './signIn-
|
|
4
|
+
import { S as SessionManager, a as SessionSnapshot, b as SignInOptions, c as SignOutOptions, C as CallbackResult } from './signIn-Cd0P4y9d.mjs';
|
|
5
5
|
import { d as SessionUser, J as JwtClaims } from './types-Cxl3bQHt.mjs';
|
|
6
|
-
import './publishableKey-
|
|
6
|
+
import './publishableKey-BaR0HoAH.mjs';
|
|
7
7
|
|
|
8
8
|
interface IQAuthContextValue {
|
|
9
9
|
manager: SessionManager;
|
|
@@ -89,6 +89,38 @@ declare function SignedOut({ children }: {
|
|
|
89
89
|
}): React.FunctionComponentElement<{
|
|
90
90
|
children?: ReactNode | undefined;
|
|
91
91
|
}> | null;
|
|
92
|
+
/**
|
|
93
|
+
* Renders its children only while the SDK is still bootstrapping (i.e.
|
|
94
|
+
* `useAuth().isLoaded === false`). Mirrors Clerk's `<ClerkLoading/>`.
|
|
95
|
+
*
|
|
96
|
+
* Recommended pattern (slow-network-safe):
|
|
97
|
+
* ```tsx
|
|
98
|
+
* <IQAuthProvider publishableKey={…}>
|
|
99
|
+
* <IQAuthLoading><Spinner /></IQAuthLoading>
|
|
100
|
+
* <IQAuthLoaded>
|
|
101
|
+
* <SignedIn><App /></SignedIn>
|
|
102
|
+
* <SignedOut><SignIn /></SignedOut>
|
|
103
|
+
* </IQAuthLoaded>
|
|
104
|
+
* </IQAuthProvider>
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
declare function IQAuthLoading({ children }: {
|
|
108
|
+
children?: ReactNode;
|
|
109
|
+
}): React.FunctionComponentElement<{
|
|
110
|
+
children?: ReactNode | undefined;
|
|
111
|
+
}> | null;
|
|
112
|
+
/**
|
|
113
|
+
* Renders its children only after the SDK has finished bootstrapping (i.e.
|
|
114
|
+
* `useAuth().isLoaded === true`). Mirrors Clerk's `<ClerkLoaded/>`. Wrap
|
|
115
|
+
* `<SignedIn/>` / `<SignedOut/>` in this to avoid a flash of blank UI on
|
|
116
|
+
* slow connections — see `<IQAuthLoading/>` above for the recommended
|
|
117
|
+
* full pattern.
|
|
118
|
+
*/
|
|
119
|
+
declare function IQAuthLoaded({ children }: {
|
|
120
|
+
children?: ReactNode;
|
|
121
|
+
}): React.FunctionComponentElement<{
|
|
122
|
+
children?: ReactNode | undefined;
|
|
123
|
+
}> | null;
|
|
92
124
|
interface RedirectToSignInProps extends SignInOptions {
|
|
93
125
|
}
|
|
94
126
|
declare function RedirectToSignIn(props?: RedirectToSignInProps): React.DetailedReactHTMLElement<{
|
|
@@ -268,4 +300,4 @@ interface OrganizationSwitcherProps {
|
|
|
268
300
|
declare function OrganizationSwitcher({ iqAuthBaseUrl, onSwitched, className }: OrganizationSwitcherProps): react_jsx_runtime.JSX.Element;
|
|
269
301
|
declare const __version__ = "phase-bc-1.0.0";
|
|
270
302
|
|
|
271
|
-
export { AuthCallback, type AuthCallbackProps, type IQAuthBranding, IQAuthProvider, type IQAuthProviderProps, type IQAuthSignInContext, OrganizationSwitcher, type OrganizationSwitcherProps, RedirectToSignIn, type RedirectToSignInProps, type SessionError, type SharedComponentProps, SignIn, type SignInProps, SignUp, type SignUpProps, SignedIn, SignedOut, type UseAuthResult, type UseOrganizationResult, type UseSessionResult, type UseUserResult, UserButton, type UserButtonProps, UserProfile, type UserProfileProps, type UserSummary, __version__, isSilentSsoEligible, sanitizeBrandCss, useAuth, useAuthFetch, useIQAuthSignInContext, useOrganization, useResolvedSdkBranding, useSession, useUser };
|
|
303
|
+
export { AuthCallback, type AuthCallbackProps, type IQAuthBranding, IQAuthLoaded, IQAuthLoading, IQAuthProvider, type IQAuthProviderProps, type IQAuthSignInContext, OrganizationSwitcher, type OrganizationSwitcherProps, RedirectToSignIn, type RedirectToSignInProps, type SessionError, type SharedComponentProps, SignIn, type SignInProps, SignUp, type SignUpProps, SignedIn, SignedOut, type UseAuthResult, type UseOrganizationResult, type UseSessionResult, type UseUserResult, UserButton, type UserButtonProps, UserProfile, type UserProfileProps, type UserSummary, __version__, isSilentSsoEligible, sanitizeBrandCss, useAuth, useAuthFetch, useIQAuthSignInContext, useOrganization, useResolvedSdkBranding, useSession, useUser };
|
package/dist/react.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
|
-
import { S as SessionManager, a as SessionSnapshot, b as SignInOptions, c as SignOutOptions, C as CallbackResult } from './signIn-
|
|
4
|
+
import { S as SessionManager, a as SessionSnapshot, b as SignInOptions, c as SignOutOptions, C as CallbackResult } from './signIn-DKakyzeu.js';
|
|
5
5
|
import { d as SessionUser, J as JwtClaims } from './types-Cxl3bQHt.js';
|
|
6
|
-
import './publishableKey-
|
|
6
|
+
import './publishableKey-BaR0HoAH.js';
|
|
7
7
|
|
|
8
8
|
interface IQAuthContextValue {
|
|
9
9
|
manager: SessionManager;
|
|
@@ -89,6 +89,38 @@ declare function SignedOut({ children }: {
|
|
|
89
89
|
}): React.FunctionComponentElement<{
|
|
90
90
|
children?: ReactNode | undefined;
|
|
91
91
|
}> | null;
|
|
92
|
+
/**
|
|
93
|
+
* Renders its children only while the SDK is still bootstrapping (i.e.
|
|
94
|
+
* `useAuth().isLoaded === false`). Mirrors Clerk's `<ClerkLoading/>`.
|
|
95
|
+
*
|
|
96
|
+
* Recommended pattern (slow-network-safe):
|
|
97
|
+
* ```tsx
|
|
98
|
+
* <IQAuthProvider publishableKey={…}>
|
|
99
|
+
* <IQAuthLoading><Spinner /></IQAuthLoading>
|
|
100
|
+
* <IQAuthLoaded>
|
|
101
|
+
* <SignedIn><App /></SignedIn>
|
|
102
|
+
* <SignedOut><SignIn /></SignedOut>
|
|
103
|
+
* </IQAuthLoaded>
|
|
104
|
+
* </IQAuthProvider>
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
declare function IQAuthLoading({ children }: {
|
|
108
|
+
children?: ReactNode;
|
|
109
|
+
}): React.FunctionComponentElement<{
|
|
110
|
+
children?: ReactNode | undefined;
|
|
111
|
+
}> | null;
|
|
112
|
+
/**
|
|
113
|
+
* Renders its children only after the SDK has finished bootstrapping (i.e.
|
|
114
|
+
* `useAuth().isLoaded === true`). Mirrors Clerk's `<ClerkLoaded/>`. Wrap
|
|
115
|
+
* `<SignedIn/>` / `<SignedOut/>` in this to avoid a flash of blank UI on
|
|
116
|
+
* slow connections — see `<IQAuthLoading/>` above for the recommended
|
|
117
|
+
* full pattern.
|
|
118
|
+
*/
|
|
119
|
+
declare function IQAuthLoaded({ children }: {
|
|
120
|
+
children?: ReactNode;
|
|
121
|
+
}): React.FunctionComponentElement<{
|
|
122
|
+
children?: ReactNode | undefined;
|
|
123
|
+
}> | null;
|
|
92
124
|
interface RedirectToSignInProps extends SignInOptions {
|
|
93
125
|
}
|
|
94
126
|
declare function RedirectToSignIn(props?: RedirectToSignInProps): React.DetailedReactHTMLElement<{
|
|
@@ -268,4 +300,4 @@ interface OrganizationSwitcherProps {
|
|
|
268
300
|
declare function OrganizationSwitcher({ iqAuthBaseUrl, onSwitched, className }: OrganizationSwitcherProps): react_jsx_runtime.JSX.Element;
|
|
269
301
|
declare const __version__ = "phase-bc-1.0.0";
|
|
270
302
|
|
|
271
|
-
export { AuthCallback, type AuthCallbackProps, type IQAuthBranding, IQAuthProvider, type IQAuthProviderProps, type IQAuthSignInContext, OrganizationSwitcher, type OrganizationSwitcherProps, RedirectToSignIn, type RedirectToSignInProps, type SessionError, type SharedComponentProps, SignIn, type SignInProps, SignUp, type SignUpProps, SignedIn, SignedOut, type UseAuthResult, type UseOrganizationResult, type UseSessionResult, type UseUserResult, UserButton, type UserButtonProps, UserProfile, type UserProfileProps, type UserSummary, __version__, isSilentSsoEligible, sanitizeBrandCss, useAuth, useAuthFetch, useIQAuthSignInContext, useOrganization, useResolvedSdkBranding, useSession, useUser };
|
|
303
|
+
export { AuthCallback, type AuthCallbackProps, type IQAuthBranding, IQAuthLoaded, IQAuthLoading, IQAuthProvider, type IQAuthProviderProps, type IQAuthSignInContext, OrganizationSwitcher, type OrganizationSwitcherProps, RedirectToSignIn, type RedirectToSignInProps, type SessionError, type SharedComponentProps, SignIn, type SignInProps, SignUp, type SignUpProps, SignedIn, SignedOut, type UseAuthResult, type UseOrganizationResult, type UseSessionResult, type UseUserResult, UserButton, type UserButtonProps, UserProfile, type UserProfileProps, type UserSummary, __version__, isSilentSsoEligible, sanitizeBrandCss, useAuth, useAuthFetch, useIQAuthSignInContext, useOrganization, useResolvedSdkBranding, useSession, useUser };
|
package/dist/react.js
CHANGED
|
@@ -21,6 +21,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var react_exports = {};
|
|
22
22
|
__export(react_exports, {
|
|
23
23
|
AuthCallback: () => AuthCallback,
|
|
24
|
+
IQAuthLoaded: () => IQAuthLoaded,
|
|
25
|
+
IQAuthLoading: () => IQAuthLoading,
|
|
24
26
|
IQAuthProvider: () => IQAuthProvider,
|
|
25
27
|
OrganizationSwitcher: () => OrganizationSwitcher,
|
|
26
28
|
RedirectToSignIn: () => RedirectToSignIn,
|
|
@@ -70,20 +72,60 @@ function b64urlDecode(input) {
|
|
|
70
72
|
const { Buffer: Buffer2 } = require("buffer");
|
|
71
73
|
return Buffer2.from(normalized, "base64").toString("utf8");
|
|
72
74
|
}
|
|
73
|
-
function
|
|
74
|
-
if (typeof
|
|
75
|
-
|
|
76
|
-
if (!m) return null;
|
|
75
|
+
function isValidIssuerUrl(iss) {
|
|
76
|
+
if (typeof iss !== "string" || iss.length === 0) return false;
|
|
77
|
+
if (!iss.startsWith("http://") && !iss.startsWith("https://")) return false;
|
|
77
78
|
try {
|
|
78
|
-
const
|
|
79
|
-
if (
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
return { mode: m[1], iss: json.iss, appId: json.appId, tenantId: json.tenantId, kid: json.kid, raw };
|
|
79
|
+
const u = new URL(iss);
|
|
80
|
+
if (u.protocol !== "http:" && u.protocol !== "https:") return false;
|
|
81
|
+
if (!u.hostname) return false;
|
|
82
|
+
return true;
|
|
84
83
|
} catch {
|
|
85
|
-
return
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function assertPublishableKey(raw, opts) {
|
|
88
|
+
const ctx = opts?.context ? `${opts.context}: ` : "";
|
|
89
|
+
if (typeof raw !== "string" || raw.length === 0) {
|
|
90
|
+
throw new IQAuthError(
|
|
91
|
+
"CONFIG_INVALID",
|
|
92
|
+
`${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.`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
const shapeMatch = raw.match(/^pk_(test|live)_([A-Za-z0-9_-]+)$/);
|
|
96
|
+
if (!shapeMatch) {
|
|
97
|
+
throw new IQAuthError(
|
|
98
|
+
"CONFIG_INVALID",
|
|
99
|
+
`${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.`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
let decoded;
|
|
103
|
+
try {
|
|
104
|
+
decoded = JSON.parse(b64urlDecode(shapeMatch[2]));
|
|
105
|
+
} catch {
|
|
106
|
+
throw new IQAuthError(
|
|
107
|
+
"CONFIG_INVALID",
|
|
108
|
+
`${ctx}IQAuth publishable key payload is not valid base64url JSON. Regenerate the key from the IQAuth admin console.`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
if (!isPublishableKeyPayload(decoded)) {
|
|
112
|
+
throw new IQAuthError(
|
|
113
|
+
"CONFIG_INVALID",
|
|
114
|
+
`${ctx}IQAuth publishable key payload is missing required fields {iss, appId, tenantId, kid}. Regenerate the key from the IQAuth admin console.`
|
|
115
|
+
);
|
|
86
116
|
}
|
|
117
|
+
if (!isValidIssuerUrl(decoded.iss)) {
|
|
118
|
+
throw new IQAuthError(
|
|
119
|
+
"CONFIG_INVALID",
|
|
120
|
+
`${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 \u2014 the new key will encode a valid issuer URL.`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
return { mode: shapeMatch[1], iss: decoded.iss, appId: decoded.appId, tenantId: decoded.tenantId, kid: decoded.kid, raw };
|
|
124
|
+
}
|
|
125
|
+
function isPublishableKeyPayload(value) {
|
|
126
|
+
if (!value || typeof value !== "object") return false;
|
|
127
|
+
const v = value;
|
|
128
|
+
return typeof v.iss === "string" && typeof v.appId === "string" && typeof v.tenantId === "string" && typeof v.kid === "string";
|
|
87
129
|
}
|
|
88
130
|
|
|
89
131
|
// src/browser/storage.ts
|
|
@@ -206,12 +248,7 @@ var SessionManager = class {
|
|
|
206
248
|
this.remoteRefreshWaiters = [];
|
|
207
249
|
/** Active claims by other tabs (keyed by source tabId). */
|
|
208
250
|
this.foreignClaim = null;
|
|
209
|
-
const parsed =
|
|
210
|
-
if (!parsed) {
|
|
211
|
-
throw new Error(
|
|
212
|
-
`Invalid IQAuth publishable key. Expected pk_test_\u2026 or pk_live_\u2026 (got ${options.publishableKey?.slice(0, 12) ?? "<empty>"}\u2026).`
|
|
213
|
-
);
|
|
214
|
-
}
|
|
251
|
+
const parsed = assertPublishableKey(options.publishableKey, { context: "@iqauth/sdk/browser SessionManager" });
|
|
215
252
|
this.key = parsed;
|
|
216
253
|
const inferred = options.issuer ?? (parsed.iss.startsWith("http") ? parsed.iss : `https://${parsed.iss}`);
|
|
217
254
|
this.issuer = inferred.replace(/\/+$/, "");
|
|
@@ -612,6 +649,7 @@ async function createPkcePair() {
|
|
|
612
649
|
// src/browser/signIn.ts
|
|
613
650
|
var DEFAULT_SIGN_IN_PATH = "/sign-in";
|
|
614
651
|
var DEFAULT_LOGOUT_PATH = "/api/v1/auth/logout";
|
|
652
|
+
var DEFAULT_SSO_LOGOUT_PATH = "/oidc/sso-logout";
|
|
615
653
|
var DEFAULT_TOKEN_PATH = "/oidc/token";
|
|
616
654
|
var DEFAULT_CALLBACK_PATH = "/auth/callback";
|
|
617
655
|
function defaultRedirectUri() {
|
|
@@ -710,11 +748,21 @@ async function handleAuthCallback(manager, options = {}) {
|
|
|
710
748
|
}
|
|
711
749
|
async function signOut(manager, opts = {}) {
|
|
712
750
|
if (!opts.localOnly) {
|
|
751
|
+
const issuer = manager.issuerUrl.replace(/\/$/, "");
|
|
713
752
|
try {
|
|
714
|
-
const url = `${
|
|
753
|
+
const url = `${issuer}${opts.logoutPath ?? DEFAULT_LOGOUT_PATH}`;
|
|
715
754
|
await manager.fetch(url, { method: "POST" }).catch(() => void 0);
|
|
716
755
|
} catch {
|
|
717
756
|
}
|
|
757
|
+
if (opts.endSsoSession !== false) {
|
|
758
|
+
try {
|
|
759
|
+
await fetch(`${issuer}${DEFAULT_SSO_LOGOUT_PATH}`, {
|
|
760
|
+
method: "POST",
|
|
761
|
+
credentials: "include"
|
|
762
|
+
}).catch(() => void 0);
|
|
763
|
+
} catch {
|
|
764
|
+
}
|
|
765
|
+
}
|
|
718
766
|
}
|
|
719
767
|
clearCookie(REFRESH_COOKIE);
|
|
720
768
|
manager.signOutLocal();
|
|
@@ -846,6 +894,16 @@ function SignedOut({ children }) {
|
|
|
846
894
|
if (!isLoaded || isSignedIn) return null;
|
|
847
895
|
return (0, import_react.createElement)(import_react.Fragment, null, children);
|
|
848
896
|
}
|
|
897
|
+
function IQAuthLoading({ children }) {
|
|
898
|
+
const { isLoaded } = useAuth();
|
|
899
|
+
if (isLoaded) return null;
|
|
900
|
+
return (0, import_react.createElement)(import_react.Fragment, null, children);
|
|
901
|
+
}
|
|
902
|
+
function IQAuthLoaded({ children }) {
|
|
903
|
+
const { isLoaded } = useAuth();
|
|
904
|
+
if (!isLoaded) return null;
|
|
905
|
+
return (0, import_react.createElement)(import_react.Fragment, null, children);
|
|
906
|
+
}
|
|
849
907
|
function RedirectToSignIn(props = {}) {
|
|
850
908
|
const { manager, snapshot } = useCtx();
|
|
851
909
|
const [error, setError] = (0, import_react.useState)(null);
|
|
@@ -1868,6 +1926,8 @@ var __version__ = "phase-bc-1.0.0";
|
|
|
1868
1926
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1869
1927
|
0 && (module.exports = {
|
|
1870
1928
|
AuthCallback,
|
|
1929
|
+
IQAuthLoaded,
|
|
1930
|
+
IQAuthLoading,
|
|
1871
1931
|
IQAuthProvider,
|
|
1872
1932
|
OrganizationSwitcher,
|
|
1873
1933
|
RedirectToSignIn,
|
package/dist/react.mjs
CHANGED
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
redirectToSignIn,
|
|
5
5
|
signIn,
|
|
6
6
|
signOut
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-RACIPVLD.mjs";
|
|
8
|
+
import "./chunk-WQWBJSSS.mjs";
|
|
9
9
|
import "./chunk-6I6RM4MN.mjs";
|
|
10
10
|
import "./chunk-Y6FXYEAI.mjs";
|
|
11
11
|
|
|
@@ -144,6 +144,16 @@ function SignedOut({ children }) {
|
|
|
144
144
|
if (!isLoaded || isSignedIn) return null;
|
|
145
145
|
return createElement(Fragment, null, children);
|
|
146
146
|
}
|
|
147
|
+
function IQAuthLoading({ children }) {
|
|
148
|
+
const { isLoaded } = useAuth();
|
|
149
|
+
if (isLoaded) return null;
|
|
150
|
+
return createElement(Fragment, null, children);
|
|
151
|
+
}
|
|
152
|
+
function IQAuthLoaded({ children }) {
|
|
153
|
+
const { isLoaded } = useAuth();
|
|
154
|
+
if (!isLoaded) return null;
|
|
155
|
+
return createElement(Fragment, null, children);
|
|
156
|
+
}
|
|
147
157
|
function RedirectToSignIn(props = {}) {
|
|
148
158
|
const { manager, snapshot } = useCtx();
|
|
149
159
|
const [error, setError] = useState(null);
|
|
@@ -1165,6 +1175,8 @@ function OrganizationSwitcher({ iqAuthBaseUrl, onSwitched, className }) {
|
|
|
1165
1175
|
var __version__ = "phase-bc-1.0.0";
|
|
1166
1176
|
export {
|
|
1167
1177
|
AuthCallback,
|
|
1178
|
+
IQAuthLoaded,
|
|
1179
|
+
IQAuthLoading,
|
|
1168
1180
|
IQAuthProvider,
|
|
1169
1181
|
OrganizationSwitcher,
|
|
1170
1182
|
RedirectToSignIn,
|
|
@@ -118,6 +118,8 @@ declare function handleRefresh(config: IQAuthHelperConfig, input: {
|
|
|
118
118
|
/** POST /api/iqauth/signout — clear cookies and best-effort revoke at issuer. */
|
|
119
119
|
declare function handleSignout(config: IQAuthHelperConfig, input: {
|
|
120
120
|
accessToken?: string;
|
|
121
|
+
ssoCookieHeader?: string;
|
|
122
|
+
endSsoSession?: boolean;
|
|
121
123
|
}): Promise<HandlerResponse>;
|
|
122
124
|
|
|
123
125
|
export { type HandlerResponse, type IQAuthHelperConfig, type ResolvedConfig as ResolvedIQAuthHelperConfig, type SetCookieDirective, handleCallback, handleRefresh, handleSignout, serializeCookie };
|
|
@@ -118,6 +118,8 @@ declare function handleRefresh(config: IQAuthHelperConfig, input: {
|
|
|
118
118
|
/** POST /api/iqauth/signout — clear cookies and best-effort revoke at issuer. */
|
|
119
119
|
declare function handleSignout(config: IQAuthHelperConfig, input: {
|
|
120
120
|
accessToken?: string;
|
|
121
|
+
ssoCookieHeader?: string;
|
|
122
|
+
endSsoSession?: boolean;
|
|
121
123
|
}): Promise<HandlerResponse>;
|
|
122
124
|
|
|
123
125
|
export { type HandlerResponse, type IQAuthHelperConfig, type ResolvedConfig as ResolvedIQAuthHelperConfig, type SetCookieDirective, handleCallback, handleRefresh, handleSignout, serializeCookie };
|
package/dist/server/handlers.js
CHANGED
|
@@ -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
|
|
44
|
-
if (typeof
|
|
45
|
-
|
|
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
|
|
49
|
-
if (
|
|
50
|
-
if (
|
|
51
|
-
|
|
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;
|
|
54
62
|
} catch {
|
|
55
|
-
return
|
|
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]));
|
|
84
|
+
} catch {
|
|
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
|
+
);
|
|
56
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
|
+
);
|
|
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 \u2014 the new key will encode a valid issuer URL.`
|
|
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 =
|
|
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,
|
|
@@ -252,6 +298,15 @@ async function handleSignout(config, input) {
|
|
|
252
298
|
} catch {
|
|
253
299
|
}
|
|
254
300
|
}
|
|
301
|
+
if (input.endSsoSession !== false && input.ssoCookieHeader) {
|
|
302
|
+
try {
|
|
303
|
+
await cfg.fetchImpl(`${cfg.issuer}/oidc/sso-logout`, {
|
|
304
|
+
method: "POST",
|
|
305
|
+
headers: { Cookie: input.ssoCookieHeader }
|
|
306
|
+
});
|
|
307
|
+
} catch {
|
|
308
|
+
}
|
|
309
|
+
}
|
|
255
310
|
return {
|
|
256
311
|
status: 200,
|
|
257
312
|
body: { success: true, data: { signedOut: true } },
|
package/dist/server/handlers.mjs
CHANGED
|
@@ -3,8 +3,9 @@ import {
|
|
|
3
3
|
handleRefresh,
|
|
4
4
|
handleSignout,
|
|
5
5
|
serializeCookie
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-KGEPDXHU.mjs";
|
|
7
|
+
import "../chunk-WQWBJSSS.mjs";
|
|
8
|
+
import "../chunk-6I6RM4MN.mjs";
|
|
8
9
|
import "../chunk-Y6FXYEAI.mjs";
|
|
9
10
|
export {
|
|
10
11
|
handleCallback,
|
package/dist/server.d.mts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { b as IQAuthTokenClientConfig, N as ExpressMiddlewareOptions, Q as IQAuthRequestLike, R as IQAuthResponseLike, V as IQAuthNextFunction } from './types-Cxl3bQHt.mjs';
|
|
2
|
-
import { I as IQAuthClient } from './client-
|
|
2
|
+
import { I as IQAuthClient } from './client-vdh2a9fJ.mjs';
|
|
3
3
|
export { E as ErrorCodes, I as IQAuthError } from './errors-CDdl24MP.mjs';
|
|
4
|
-
export { C as CookieAwareMiddlewareOptions, D as DEFAULT_ACCESS_COOKIE, a as DEFAULT_REFRESH_COOKIE, i as iqAuthMiddleware } from './express-
|
|
4
|
+
export { C as CookieAwareMiddlewareOptions, D as DEFAULT_ACCESS_COOKIE, a as DEFAULT_REFRESH_COOKIE, i as iqAuthMiddleware } from './express-A0-dWEMy.mjs';
|
|
5
5
|
export { HandlerResponse, IQAuthHelperConfig, SetCookieDirective, handleCallback, handleRefresh, handleSignout, serializeCookie } from './server/handlers.mjs';
|
|
6
|
-
import 'jsonwebtoken';
|
|
7
6
|
|
|
8
7
|
declare class ServerIQAuthClient extends IQAuthClient {
|
|
9
8
|
constructor(config: IQAuthTokenClientConfig);
|
package/dist/server.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { b as IQAuthTokenClientConfig, N as ExpressMiddlewareOptions, Q as IQAuthRequestLike, R as IQAuthResponseLike, V as IQAuthNextFunction } from './types-Cxl3bQHt.js';
|
|
2
|
-
import { I as IQAuthClient } from './client-
|
|
2
|
+
import { I as IQAuthClient } from './client-DTX4hNdS.js';
|
|
3
3
|
export { E as ErrorCodes, I as IQAuthError } from './errors-CDdl24MP.js';
|
|
4
|
-
export { C as CookieAwareMiddlewareOptions, D as DEFAULT_ACCESS_COOKIE, a as DEFAULT_REFRESH_COOKIE, i as iqAuthMiddleware } from './express-
|
|
4
|
+
export { C as CookieAwareMiddlewareOptions, D as DEFAULT_ACCESS_COOKIE, a as DEFAULT_REFRESH_COOKIE, i as iqAuthMiddleware } from './express-Bo_pJKHN.js';
|
|
5
5
|
export { HandlerResponse, IQAuthHelperConfig, SetCookieDirective, handleCallback, handleRefresh, handleSignout, serializeCookie } from './server/handlers.js';
|
|
6
|
-
import 'jsonwebtoken';
|
|
7
6
|
|
|
8
7
|
declare class ServerIQAuthClient extends IQAuthClient {
|
|
9
8
|
constructor(config: IQAuthTokenClientConfig);
|