Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
],
"private": false,
"dependencies": {
"@kinde/js-utils": "0.29.0"
"@kinde/js-utils": "0.29.1-5"
},
"packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977"
}
53 changes: 50 additions & 3 deletions src/state/KindeProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,15 @@ export const KindeProvider = ({
activityTimeout,
refreshOnFocus = false,
}: KindeProviderProps) => {
const mergedCallbacks = { ...defaultCallbacks, ...callbacks };
// Check for invitation_code synchronously before any hooks/rendering
const params = new URLSearchParams(window.location.search);
const hasInvitationCode = params.has("invitation_code");
const invitationCodeRef = useRef<string | null>(
hasInvitationCode ? params.get("invitation_code") : null,
);
const isRedirectingRef = useRef(hasInvitationCode);

const mergedCallbacks = { ...defaultCallbacks, ...callbacks };
// Track if activity tracking is currently enabled
const [isActivityTrackingEnabled, setIsActivityTrackingEnabled] =
useState(false);
Expand All @@ -241,7 +248,11 @@ export const KindeProvider = ({
const handleLocationChange = useCallback(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
(_loc: Location) => {
if (isActivityTrackingEnabled && activityTimeout && state.isAuthenticated) {
if (
isActivityTrackingEnabled &&
activityTimeout &&
state.isAuthenticated
) {
updateActivityTimestamp();
}
},
Expand Down Expand Up @@ -361,6 +372,8 @@ export const KindeProvider = ({
storageSettings.useInsecureForRefreshToken = useInsecureForRefreshToken;

const initRef = useRef(false);
const loginRef = useRef<typeof login | null>(null);
const redirectInitiatedRef = useRef(false);

const login = useCallback(
async (
Expand Down Expand Up @@ -419,6 +432,29 @@ export const KindeProvider = ({
],
);

// Store login in ref for immediate access
loginRef.current = login;

// Handle invitation_code redirect immediately, before any render
useEffect(() => {
if (
isRedirectingRef.current &&
invitationCodeRef.current &&
login &&
!redirectInitiatedRef.current
) {
redirectInitiatedRef.current = true;
login({
prompt: PromptTypes.create,
invitationCode: invitationCodeRef.current,
}).catch((error) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DanielRivers Should this be going to Login or Register? What if the user doesn't have an account?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is correct, forces registration flow

console.error("Error processing invitation code:", error);
isRedirectingRef.current = false;
redirectInitiatedRef.current = false;
});
}
}, [login]); // Include login to ensure it's ready when it becomes available

const register = useCallback(
async (
options: LoginMethodParams & { state?: Record<string, string> } = {},
Expand Down Expand Up @@ -749,14 +785,20 @@ export const KindeProvider = ({
const init = useCallback(async () => {
if (initRef.current) return;
try {
const params = new URLSearchParams(window.location.search);

// Skip initialization if redirecting for invitation (handled in useEffect above)
if (isRedirectingRef.current) {
return;
}

try {
initRef.current = true;
await checkAuth({ domain, clientId });
} catch (err) {
console.warn("checkAuth failed:", err);
setState((v: ProviderState) => ({ ...v, isLoading: false }));
}
const params = new URLSearchParams(window.location.search);

if (params.has("error")) {
const errorCode = params.get("error");
Expand Down Expand Up @@ -845,6 +887,11 @@ export const KindeProvider = ({
};
}, [init]);

// Don't render children if redirecting for invitation
if (isRedirectingRef.current && !forceChildrenRender) {
return <></>;
}

return forceChildrenRender || initRef.current ? (
<KindeContext.Provider value={contextValue}>
{children}
Expand Down