@kinde-oss/kinde-auth-react
Version:
Kinde React SDK for authentication
481 lines (480 loc) • 13.8 kB
JavaScript
import { K as ge } from "./useKindeAuth-DZGdOK3E.js";
import { u as ze } from "./useKindeAuth-DZGdOK3E.js";
import { jsx as q, Fragment as he } from "react/jsx-runtime";
import { LocalStorage as fe, MemoryStorage as de, setActiveStorage as oe, setInsecureStorage as we, storageSettings as w, updateActivityTimestamp as B, isAuthenticated as me, getUserProfile as O, frameworkSettings as $, base64UrlEncode as Q, generateAuthUrl as Y, IssuerRouteTypes as ee, navigateToKinde as K, PromptTypes as te, StorageKeys as y, refreshToken as re, generatePortalUrl as ye, getRoles as Se, getUserOrganizations as ve, getPermissions as pe, getPermission as Re, getFlag as ke, getCurrentOrganization as se, getClaims as Ee, getClaim as Pe, getActiveStorage as N, exchangeAuthCode as Ae, checkAuth as Te } from "./utils.mjs";
import Le, { useState as ne, useCallback as d, useEffect as D, useRef as ae, useMemo as be } from "react";
var x = /* @__PURE__ */ ((n) => (n.performingLogout = "performing_logout", n))(x || {});
const ie = new de(), T = new fe();
oe(ie);
we(T);
const W = (n) => n || window.location.origin, Ue = "5.10.1", _e = {
version: Ue
};
var ce = /* @__PURE__ */ ((n) => (n.preWarning = "preWarning", n.timeout = "timeout", n))(ce || {});
w.keyPrefix = "";
const Ce = () => {
window.history.replaceState({}, document.title, window.location.pathname);
}, Oe = {
onSuccess: Ce
}, z = () => {
try {
const n = window.opener;
return !n || n.closed ? !1 : n.location.origin === window.location.origin;
} catch {
return !1;
}
}, De = (n, { skipInitial: p = !1 } = {}) => {
const c = ae(!0);
D(() => {
const R = () => {
if (p && c.current) {
c.current = !1;
return;
}
n(window.location);
}, o = () => R();
window.addEventListener("popstate", o), window.addEventListener("hashchange", o);
const k = history.pushState, u = history.replaceState;
return history.pushState === k && (history.pushState = function(...E) {
k.apply(this, E), R();
}), history.replaceState === u && (history.replaceState = function(...E) {
u.apply(this, E), R();
}), () => {
window.removeEventListener("popstate", o), window.removeEventListener("hashchange", o), history.pushState = k, history.replaceState = u;
};
}, [n, p]);
}, Ke = ({
audience: n,
scope: p,
clientId: c,
children: R,
domain: o,
useInsecureForRefreshToken: k = !1,
redirectUri: u,
callbacks: E = {},
logoutUri: L,
forceChildrenRender: ue = !1,
popupOptions: S = {},
store: m = ie,
activityTimeout: f,
refreshOnFocus: b = !1
}) => {
const a = { ...Oe, ...E }, [P, F] = ne(!1), [v, h] = ne({
user: void 0,
isAuthenticated: !1,
isLoading: !0
}), le = d(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
(e) => {
P && f && v.isAuthenticated && B();
},
[P, f, v.isAuthenticated]
);
De(
le,
f ? {} : { skipInitial: !0 }
), D(() => {
oe(m);
const e = () => {
if (!(!f || P)) {
w.activityTimeoutMinutes = f.timeoutMinutes, w.activityTimeoutPreWarningMinutes = f.preWarningMinutes, w.onActivityTimeout = async (t, r) => {
try {
if (t === ce.timeout) {
const g = r?.accessToken, M = r?.refreshToken, V = async (X, H) => {
if (!X) return;
const Z = await fetch(`${o}/oauth2/revoke`, {
method: "POST",
body: `token=${encodeURIComponent(X)}&client_id=${encodeURIComponent(c)}&token_type_hint=${H}`,
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
});
Z.ok || console.warn(
`Failed to revoke ${H}:`,
Z.status
);
};
await Promise.allSettled([
V(g, "access_token"),
V(M, "refresh_token")
]);
}
} catch (g) {
console.error("Failed to logout:", g);
} finally {
f.onTimeout?.(t);
}
};
try {
B();
} catch (t) {
console.error("Failed to update activity timestamp:", t);
return;
}
F(!0);
}
}, s = () => {
P && (w.activityTimeoutMinutes = void 0, w.activityTimeoutPreWarningMinutes = void 0, w.onActivityTimeout = void 0, F(!1));
}, i = m.subscribe(async () => {
try {
const [t, r] = await Promise.all([
me(),
O()
]);
t && r ? (e(), h((g) => ({ ...g, user: r, isAuthenticated: !0 }))) : (s(), h((g) => ({
...g,
user: void 0,
isAuthenticated: !1
})));
} catch (t) {
console.error("Store subscription update failed:", t), s(), h((r) => ({
...r,
user: void 0,
isAuthenticated: !1
}));
}
});
return () => {
i(), s();
};
}, [m, f, P]), $.framework = "react", $.frameworkVersion = Le.version, $.sdkVersion = _e.version, w.useInsecureForRefreshToken = k;
const I = ae(!1), U = d(
async (e = {}) => {
const s = e.state || {};
e.state = void 0;
const i = {
audience: n,
clientId: c,
...e,
supportsReauth: !0,
scope: p?.split(" "),
state: Q(
JSON.stringify({
kinde: {
event: "login"
/* login */
},
...s
})
),
redirectURL: W(e.redirectURL || u)
}, t = await Y(
o,
ee.login,
i
);
try {
K({
url: t.url.toString(),
popupOptions: S,
handleResult: _
});
} catch (r) {
a.onError?.(
{
error: "ERR_POPUP",
errorDescription: r.message
},
{},
{}
);
}
},
[
n,
c,
u,
S,
a,
o,
p
]
), J = d(
async (e = {}) => {
const s = e.state || {};
e.state = void 0;
const i = {
...e,
state: Q(
JSON.stringify({
kinde: {
event: "register"
/* register */
},
...s
})
),
supportsReauth: !0,
audience: n,
clientId: c,
redirectURL: W(e?.redirectURL || u),
prompt: te.create
};
try {
const t = await Y(
o,
ee.register,
i
);
try {
K({
url: t.url.toString(),
popupOptions: S,
handleResult: _
});
} catch (r) {
a.onError?.(
{
error: "ERR_POPUP",
errorDescription: r.message
},
{},
{}
);
}
} catch (t) {
console.error("Register error:", t), a.onError?.(
{
error: "ERR_REGISTER",
errorDescription: String(t)
},
{},
l
);
}
},
[u, S, a, n, c, o]
), j = d(
async (e) => {
try {
const s = new URLSearchParams();
e ? e && typeof e == "string" ? s.append("redirect", e) : typeof e == "object" && ((e.redirectUrl || L) && s.append("redirect", e.redirectUrl || L || ""), e.allSessions && s.append("all_sessions", String(e.allSessions))) : s.append("redirect", L || ""), await Promise.all([
m.removeSessionItem(y.idToken),
m.removeSessionItem(y.accessToken),
m.removeSessionItem(y.refreshToken),
T.removeSessionItem(y.refreshToken)
]), h((i) => ({ ...i, user: void 0, isAuthenticated: !1 })), await T.setSessionItem(
x.performingLogout,
"true"
);
try {
await K({
url: `${o}/logout?${s.toString()}`,
popupOptions: S
});
} catch (i) {
a.onError?.(
{
error: "ERR_POPUP",
errorDescription: i.message
},
{},
{}
);
}
} catch (s) {
console.error("Logout error:", s), a.onError?.(
{
error: "ERR_LOGOUT",
errorDescription: String(s)
},
{},
l
);
}
},
[m, S, a, L, o]
), l = be(() => ({
// Internal Methods
login: U,
logout: j,
register: J,
getIdToken: async () => await N()?.getSessionItem(y.idToken),
getAccessToken: async () => await N()?.getSessionItem(
y.accessToken
),
/** @deprecated use `getAccessToken` instead */
getToken: async () => await N()?.getSessionItem(
y.accessToken
),
getClaim: async (e, s) => Pe(e, s),
getClaims: async (...e) => Ee(...e),
/** @deprecated use `getCurrentOrganization` instead */
getOrganization: async () => await se(),
getCurrentOrganization: async () => await se(),
getFlag: async (e) => await ke(e),
getUserProfile: O,
getPermission: async (e) => await Re(e),
getPermissions: async () => pe(),
getUserOrganizations: async () => await ve(),
getRoles: async () => await Se(),
generatePortalUrl: async (e) => await ye({
domain: o,
returnUrl: e.returnUrl || window.location.href,
subNav: e.subNav
}),
refreshToken: async (...e) => await re(...e),
...v
}), [v, U, j, J]), A = d(
(e) => {
a.onEvent && a.onEvent("tokenRefreshed", e, l);
},
[a, l]
), _ = d(
async (e) => {
const s = atob(e.get("state") || "");
let i, t;
try {
i = JSON.parse(s), t = Object.assign(
i.kinde || { event: te.login }
);
} catch (r) {
console.error("Error parsing state:", r), a.onError?.(
{
error: "ERR_STATE_PARSE",
errorDescription: String(r)
},
{},
l
), i = {}, t = {
event: "login"
/* login */
};
}
try {
const r = await Ae({
urlParams: e,
domain: o,
clientId: c,
redirectURL: W(u),
autoRefresh: !0,
onRefresh: A
});
if (r.success) {
const g = await O();
g && (h((M) => ({ ...M, user: g, isAuthenticated: !0 })), a.onSuccess?.(
g,
{
...i,
kinde: void 0
},
l
), a.onEvent && a.onEvent(
t.event,
{
...i,
kinde: void 0
},
l
));
} else
a.onError?.(
{
error: "ERR_CODE_EXCHANGE",
errorDescription: r.error
},
i,
l
);
} catch (r) {
a.onError?.(
{
error: "ERR_POPUP_AUTH",
errorDescription: String(r)
},
i,
l
);
} finally {
h((r) => ({ ...r, isLoading: !1 }));
}
},
[o, c, u, A, a, l]
), C = d(() => {
document.visibilityState === "visible" && v.isAuthenticated && b && re({ domain: o, clientId: c, onRefresh: A }).catch((e) => {
console.error("Error refreshing token:", e);
});
}, [v.isAuthenticated, o, c, A, b]);
D(() => {
if (document.removeEventListener("visibilitychange", C), b)
return document.addEventListener("visibilitychange", C), () => {
document.removeEventListener("visibilitychange", C);
};
}, [C, b]);
const G = d(async () => {
if (!I.current)
try {
try {
I.current = !0, await Te({ domain: o, clientId: c });
} catch (t) {
console.warn("checkAuth failed:", t), h((r) => ({ ...r, isLoading: !1 }));
}
const e = new URLSearchParams(window.location.search);
if (e.has("error")) {
if (e.get("error")?.toLowerCase() === "login_link_expired") {
const r = e.get("reauth_state");
r && U({ reauthState: r });
return;
}
h((r) => ({ ...r, isLoading: !1 }));
return;
}
await T.getSessionItem(
x.performingLogout
) === "true" && (await T.removeSessionItem(
x.performingLogout
), z() && window.close());
const s = e.has("code"), i = window.location.href.startsWith(u);
if (!s || !i) {
try {
const t = await O();
t && h((r) => ({
...r,
user: t,
isAuthenticated: !0
}));
} catch (t) {
console.warn("Error getting user profile", t);
} finally {
h((t) => ({ ...t, isLoading: !1 }));
}
return;
}
if (z()) {
const t = new URLSearchParams(window.location.search);
window.opener.postMessage(
{
type: "KINDE_AUTH_RESULT",
result: Object.fromEntries(t.entries())
},
window.location.origin
), window.close();
return;
}
await _(new URLSearchParams(window.location.search));
} finally {
z() && window.close();
}
}, [
c,
o,
u,
a,
l,
A,
U,
_
]);
return D(() => {
const e = { current: !0 };
return e.current && G(), () => {
e.current = !1;
};
}, [G]), ue || I.current ? /* @__PURE__ */ q(ge.Provider, { value: l, children: R }) : /* @__PURE__ */ q(he, {});
};
export {
ge as KindeContext,
Ke as KindeProvider,
ce as TimeoutActivityType,
ze as useKindeAuth
};