@kinde-oss/kinde-auth-react
Version:
Kinde React SDK for authentication
626 lines (625 loc) • 16.3 kB
JavaScript
import { n as e, t } from "./useKindeAuth-BFlFfLEC.js";
import { $ as n, A as r, C as i, D as a, F as o, H as ee, K as s, Q as te, Z as c, _ as l, _t as u, a as ne, ct as re, d, et as ie, g as ae, gt as f, i as oe, k as se, m as ce, mt as le, n as ue, ot as de, p, rt as m, st as h, tt as g, v as fe, w as pe, yt as _ } from "./js-utils-BNG8ijcF.js";
import me, { useCallback as v, useEffect as y, useMemo as he, useRef as b, useState as x } from "react";
import { Fragment as ge, jsx as S } from "react/jsx-runtime";
//#region src/state/store.ts
var C = /* @__PURE__ */ function(e) {
return e.performingLogout = "performing_logout", e;
}(C || {}), _e = new re(), w = new s();
ce(_e), l(w);
//#endregion
//#region src/utils/getRedirectUrl.ts
var T = (e) => e || window.location.origin, ve = {
name: "@kinde-oss/kinde-auth-react",
version: "5.13.0",
description: "Kinde React SDK for authentication",
module: "./dist/index.mjs",
main: "./dist/index.cjs",
types: "./dist/index.d.ts",
type: "module",
exports: {
".": {
types: "./dist/src/index.d.ts",
import: "./dist/index.mjs",
require: "./dist/index.cjs"
},
"./components": {
types: "./dist/src/components/index.d.ts",
import: "./dist/components.mjs",
require: "./dist/components.cjs"
},
"./utils": {
types: "./dist/src/utils/index.d.ts",
import: "./dist/utils.mjs",
require: "./dist/utils.cjs"
},
"./react-router": {
types: "./dist/src/components/react-router-dom/index.d.ts",
import: "./dist/react-router.mjs",
require: "./dist/react-router.cjs"
}
},
scripts: {
build: "tsc && vite build",
test: "vitest",
"test:coverage": "vitest --coverage",
release: "release-it",
lint: "prettier --check .",
"lint:fix": "prettier --write .",
"dev:prepare": "rm -rf playground && git clone https://github.com/kinde-starter-kits/react-starter-kit playground && cd playground && printf \"overrides:\\n '@kinde-oss/kinde-auth-react': link:..\\n\" > pnpm-workspace.yaml && pnpm install && mv .env_sample .env && rm -rf .git",
dev: "cd playground && npm start"
},
author: {
name: "Kinde",
email: "engineering@kinde.com",
url: "https://kinde.com"
},
repository: {
type: "git",
url: "https://github.com/kinde-oss/kinde-auth-react"
},
bugs: "https://github.com/kinde-oss/kinde-auth-react",
homepage: "https://kinde.com",
license: "MIT",
devDependencies: {
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^10.0.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
"@types/node": "^24.0.0",
"@types/react": "19.2.17",
"@typescript-eslint/eslint-plugin": "8.65.0",
"@typescript-eslint/parser": "8.65.0",
"@typescript/typescript6": "6.0.2",
"@vitejs/plugin-react": "^6.0.0",
"@vitest/coverage-v8": "^4.0.0",
eslint: "10.7.0",
"eslint-config-prettier": "^10.0.2",
"eslint-plugin-react": "^7.37.4",
globals: "^17.0.0",
jsdom: "^29.0.0",
prettier: "^3.5.2",
react: "^19.2.4",
"react-dom": "^19.2.4",
"release-it": "^20.0.0",
typescript: "7.0.2",
vite: "^8.0.0",
"vite-plugin-dts": "^5.0.0",
vitest: "^4.0.0"
},
keywords: [
"Kinde",
"login",
"Authorization Code Grant Flow",
"PKCE",
"Single Page Application authentication",
"React authentication"
],
peerDependencies: {
react: "^17 || ^18 || >=19.2.1",
"react-dom": "^17 || ^18 || >=19.2.1"
},
files: [
"dist",
"src",
"LICENSE.md"
],
private: !1,
dependencies: { "@kinde/js-utils": "0.32.0" },
packageManager: "pnpm@11.15.1"
}, ye = /* @__PURE__ */ function(e) {
return e.preWarning = "preWarning", e.timeout = "timeout", e;
}({});
//#endregion
//#region src/state/KindeProvider.tsx
g.keyPrefix = "";
var be = { onSuccess: () => {
window.history.replaceState({}, document.title, window.location.pathname);
} }, E = () => {
try {
let e = window.opener;
return !e || e.closed ? !1 : e.location.origin === window.location.origin;
} catch {
return !1;
}
}, xe = (e, { skipInitial: t = !1 } = {}) => {
let n = b(!0);
y(() => {
let r = () => {
if (t && n.current) {
n.current = !1;
return;
}
e(window.location);
}, i = () => r();
window.addEventListener("popstate", i), window.addEventListener("hashchange", i);
let a = history.pushState, o = history.replaceState;
return history.pushState === a && (history.pushState = function(...e) {
a.apply(this, e), r();
}), history.replaceState === o && (history.replaceState = function(...e) {
o.apply(this, e), r();
}), () => {
window.removeEventListener("popstate", i), window.removeEventListener("hashchange", i), history.pushState = a, history.replaceState = o;
};
}, [e, t]);
}, D = ({ audience: t, scope: s, clientId: l, children: re, domain: D, useInsecureForRefreshToken: Se = !1, redirectUri: O, callbacks: k = {}, logoutUri: A, forceChildrenRender: j = !1, popupOptions: M = {}, store: N = _e, activityTimeout: P, refreshOnFocus: F = !1 }) => {
let [I] = x(() => {
if (typeof window > "u") return {
invitationCode: null,
redirectPending: !1
};
let e = new URLSearchParams(window.location.search);
return {
invitationCode: e.get("invitation_code"),
redirectPending: e.has("invitation_code")
};
}), L = b(I.invitationCode), [R, z] = x(() => I.redirectPending), B = he(() => ({
...be,
...k
}), [k]), [V, Ce] = x(!1), [H, U] = x({
user: void 0,
isAuthenticated: !1,
isLoading: !0
}), [we, Te] = x(j), W = b(null), G = v((e) => {
j && U((t) => ({
...t,
isLoading: e
}));
}, [j]);
xe(v((e) => {
V && P && H.isAuthenticated && m();
}, [
V,
P,
H.isAuthenticated
]), P ? {} : { skipInitial: !0 }), y(() => {
ce(N);
let e = () => {
if (!(!P || V)) {
g.activityTimeoutMinutes = P.timeoutMinutes, g.activityTimeoutPreWarningMinutes = P.preWarningMinutes, g.onActivityTimeout = async (e, t) => {
try {
if (e === ye.timeout) {
let e = t?.accessToken, n = t?.refreshToken, r = async (e, t) => {
if (!e) return;
let n = await fetch(`${D}/oauth2/revoke`, {
method: "POST",
body: `token=${encodeURIComponent(e)}&client_id=${encodeURIComponent(l)}&token_type_hint=${t}`,
headers: { "Content-Type": "application/x-www-form-urlencoded" }
});
n.ok || console.warn(`Failed to revoke ${t}:`, n.status);
};
await Promise.allSettled([r(e, "access_token"), r(n, "refresh_token")]);
}
} catch (e) {
console.error("Failed to logout:", e);
} finally {
P.onTimeout?.(e);
}
};
try {
m();
} catch (e) {
console.error("Failed to update activity timestamp:", e);
return;
}
Ce(!0);
}
}, t = () => {
V && (g.activityTimeoutMinutes = void 0, g.activityTimeoutPreWarningMinutes = void 0, g.onActivityTimeout = void 0, Ce(!1));
}, n = N.subscribe(async () => {
try {
let [n, i] = await Promise.all([r(), p()]);
n && i ? (e(), U((e) => ({
...e,
user: i,
isAuthenticated: !0
}))) : (t(), U((e) => ({
...e,
user: void 0,
isAuthenticated: !1
})));
} catch (e) {
console.error("Store subscription update failed:", e), t(), U((e) => ({
...e,
user: void 0,
isAuthenticated: !1
}));
}
});
return () => {
n(), t();
};
}, [
N,
P,
V
]), _.framework = "react", _.frameworkVersion = me.version, _.sdkVersion = ve.version, g.useInsecureForRefreshToken = Se;
let K = b(!1), q = b(!1), J = v(async (e = {}) => {
G(!0);
let n = e.state || {};
e.state = void 0;
let r = {
audience: t,
clientId: l,
...e,
supportsReauth: !0,
scope: s?.split(" "),
state: h(JSON.stringify({
kinde: { event: "login" },
...n
})),
redirectURL: T(e.redirectURL || O)
}, i = await c(D, te.login, r);
try {
u({
url: i.url.toString(),
popupOptions: M,
handleResult: Z
});
} catch (e) {
if (G(!1), !W.current) {
console.error("Login error (context unavailable):", e);
return;
}
B.onError?.({
error: "ERR_POPUP",
errorDescription: e.message
}, {}, W.current);
}
}, [
t,
l,
O,
M,
B,
D,
s,
G
]);
y(() => {
R && L.current && !q.current && (q.current = !0, J({
prompt: f.create,
invitationCode: L.current
}).catch((e) => {
console.error("Error processing invitation code:", e), W.current ? B.onError?.({
error: "ERR_INVITATION_REDIRECT",
errorDescription: e instanceof Error ? e.message : String(e)
}, {}, W.current) : console.error("Invitation redirect error (context unavailable):", e), q.current = !1, z(!1);
}));
}, [
J,
R,
B
]);
let Ee = v(async (e = {}) => {
G(!0);
let n = e.state || {};
e.state = void 0;
let r = {
...e,
state: h(JSON.stringify({
kinde: { event: "register" },
...n
})),
supportsReauth: !0,
audience: t,
clientId: l,
redirectURL: T(e?.redirectURL || O),
prompt: f.create
};
try {
let e = await c(D, te.register, r);
try {
u({
url: e.url.toString(),
popupOptions: M,
handleResult: Z
});
} catch (e) {
if (G(!1), !W.current) {
console.error("Register error (context unavailable):", e);
return;
}
B.onError?.({
error: "ERR_POPUP",
errorDescription: e.message
}, {}, W.current);
}
} catch (e) {
if (G(!1), console.error("Register error:", e), !W.current) return;
B.onError?.({
error: "ERR_REGISTER",
errorDescription: String(e)
}, {}, W.current);
}
}, [
O,
M,
B,
t,
l,
D,
G
]), De = v(async (e) => {
G(!0);
try {
let t = new URLSearchParams();
e ? e && typeof e == "string" ? t.append("redirect", e) : typeof e == "object" && ((e.redirectUrl || A) && t.append("redirect", e.redirectUrl || A || ""), e.allSessions && t.append("all_sessions", String(e.allSessions))) : t.append("redirect", A || ""), await Promise.all([
N.removeSessionItem(a.idToken),
N.removeSessionItem(a.accessToken),
N.removeSessionItem(a.refreshToken),
w.removeSessionItem(a.refreshToken)
]), U((e) => ({
...e,
user: void 0,
isAuthenticated: !1
})), await w.setSessionItem(C.performingLogout, "true");
try {
await u({
url: `${D}/logout?${t.toString()}`,
popupOptions: M,
handleResult: async () => {
G(!1);
}
});
} catch (e) {
if (G(!1), !W.current) {
console.error("Logout error (context unavailable):", e);
return;
}
B.onError?.({
error: "ERR_POPUP",
errorDescription: e.message
}, {}, W.current);
}
} catch (e) {
if (G(!1), console.error("Logout error:", e), !W.current) return;
B.onError?.({
error: "ERR_LOGOUT",
errorDescription: String(e)
}, {}, W.current);
}
}, [
N,
M,
B,
A,
D,
G
]), Y = he(() => ({
login: J,
logout: De,
register: Ee,
getIdToken: async () => await i()?.getSessionItem(a.idToken),
getAccessToken: async () => await i()?.getSessionItem(a.accessToken),
getToken: async () => await i()?.getSessionItem(a.accessToken),
getClaim: async (e, t) => ae(e, t),
getClaims: async (...e) => fe(...e),
getOrganization: async () => await d(),
getCurrentOrganization: async () => await d(),
getFlag: async (e) => await ie(e),
getUserProfile: p,
getPermission: async (e) => await pe(e),
getPermissions: async () => oe(),
getUserOrganizations: async () => await ne(),
getRoles: async () => await se(),
generatePortalUrl: async (e) => await ue({
domain: D,
returnUrl: e.returnUrl || window.location.href,
subNav: e.subNav
}),
switchOrg: async (e) => {
let t = await n({
domain: D,
clientId: l,
orgCode: e,
redirectURL: O
});
window.location.href = t.url.toString();
},
refreshToken: async (...e) => await o(...e),
...H
}), [
H,
J,
De,
Ee,
D,
l,
O
]);
W.current = Y;
let X = v((e) => {
B.onEvent && B.onEvent("tokenRefreshed", e, Y), !e.success && B.onError && B.onError({
error: "ERR_REFRESH_TOKEN",
errorDescription: e.error ?? "Token refresh failed"
}, {}, Y);
}, [B, Y]), Z = v(async (e) => {
try {
let t = e.get("state") || "", n;
try {
n = le(t);
} catch (e) {
B.onError?.({
error: "ERR_STATE_DECODE",
errorDescription: `Invalid state parameter: ${String(e)}`
}, {}, Y), U((e) => ({
...e,
isLoading: !1
}));
return;
}
let r, i;
try {
r = JSON.parse(n), i = Object.assign(r.kinde || { event: f.login });
} catch (e) {
console.error("Error parsing state:", e), B.onError?.({
error: "ERR_STATE_PARSE",
errorDescription: String(e)
}, {}, Y), r = {}, i = { event: "login" };
}
try {
let t = await de({
urlParams: e,
domain: D,
clientId: l,
redirectURL: T(O),
autoRefresh: !0,
onRefresh: X
});
if (t.success) {
let e = await p();
e && (U((t) => ({
...t,
user: e,
isAuthenticated: !0
})), B.onSuccess?.(e, {
...r,
kinde: void 0
}, Y), B.onEvent && B.onEvent(i.event, {
...r,
kinde: void 0
}, Y));
} else B.onError?.({
error: "ERR_CODE_EXCHANGE",
errorDescription: t.error
}, r, Y);
} catch (e) {
B.onError?.({
error: "ERR_POPUP_AUTH",
errorDescription: String(e)
}, r, Y);
} finally {
j ? G(!1) : U((e) => ({
...e,
isLoading: !1
}));
}
} finally {
z(!1);
}
}, [
D,
l,
O,
X,
B,
Y,
G,
j,
z
]), Q = v(() => {
document.visibilityState === "visible" && H.isAuthenticated && F && o({
domain: D,
clientId: l,
onRefresh: X
}).then((e) => {
e.success || console.error("Error refreshing token:", e.error);
}).catch((e) => {
console.error("Error refreshing token:", e), B.onError?.({
error: "ERR_REFRESH_TOKEN",
errorDescription: e instanceof Error ? e.message : String(e)
}, {}, Y);
});
}, [
H.isAuthenticated,
D,
l,
X,
F,
B,
Y
]);
y(() => {
if (document.removeEventListener("visibilitychange", Q), F) return document.addEventListener("visibilitychange", Q), () => {
document.removeEventListener("visibilitychange", Q);
};
}, [Q, F]);
let $ = v(async () => {
if (!K.current && (j && Te(!0), !(!D || !l || !O))) try {
if (R) return;
let e = new URLSearchParams(window.location.search);
try {
K.current = !0;
let e = await ee({
domain: D,
clientId: l
});
e && !e.success && B.onError?.({
error: "ERR_CHECK_AUTH",
errorDescription: e.error ?? "Authentication check failed"
}, {}, Y);
} catch (e) {
console.warn("checkAuth failed:", e), B.onError?.({
error: "ERR_CHECK_AUTH",
errorDescription: e instanceof Error ? e.message : String(e)
}, {}, Y);
}
if (e.has("error")) {
if (e.get("error")?.toLowerCase() === "login_link_expired") {
let t = e.get("reauth_state");
t && J({ reauthState: t });
return;
}
U((e) => ({
...e,
isLoading: !1
}));
return;
}
await w.getSessionItem(C.performingLogout) === "true" && (await w.removeSessionItem(C.performingLogout), E() && window.close());
let t = new URL(window.location.href), n = new URL(O);
if (t.origin === n.origin && t.pathname === n.pathname && e.has("code")) {
if (E()) {
let e = new URLSearchParams(window.location.search);
window.opener.postMessage({
type: "KINDE_AUTH_RESULT",
result: Object.fromEntries(e.entries())
}, window.location.origin), window.close();
return;
}
await Z(new URLSearchParams(window.location.search));
return;
}
try {
let e = await p();
e && U((t) => ({
...t,
user: e,
isAuthenticated: !0
}));
} catch (e) {
console.warn("Error getting user profile", e);
} finally {
U((e) => ({
...e,
isLoading: !1
}));
}
} finally {
E() && window.close();
}
}, [
l,
D,
O,
B,
Y,
X,
J,
Z,
R,
j
]);
return y(() => {
let e = { current: !0 };
return e.current && $(), () => {
e.current = !1;
};
}, [$]), R && !j ? /* @__PURE__ */ S(ge, {}) : (j ? we : K.current) ? /* @__PURE__ */ S(e.Provider, {
value: Y,
children: re
}) : /* @__PURE__ */ S(ge, {});
};
//#endregion
export { e as KindeContext, D as KindeProvider, ye as TimeoutActivityType, t as useKindeAuth };