Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: auto login and logout functionality #3629

Merged
merged 9 commits into from
Aug 30, 2024
32 changes: 11 additions & 21 deletions src/frontend/src/components/authGuard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
import {
LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS,
LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS_ENV,
LANGFLOW_AUTO_LOGIN_OPTION,
} from "@/constants/constants";
import {
useLogout,
useRefreshAccessToken,
} from "@/controllers/API/queries/auth";
import { useRefreshAccessToken } from "@/controllers/API/queries/auth";
import { CustomNavigate } from "@/customization/components/custom-navigate";
import useAuthStore from "@/stores/authStore";
import { useEffect } from "react";
import { Cookies } from "react-cookie";

export const ProtectedRoute = ({ children }) => {
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
const hasToken = !!localStorage.getItem(LANGFLOW_AUTO_LOGIN_OPTION);

const cookies = new Cookies();
const refreshToken = cookies.get("refresh_token");
const { mutate: mutateRefresh } = useRefreshAccessToken();
const { mutate: mutationLogout } = useLogout();
const autoLogin = useAuthStore((state) => state.autoLogin);

useEffect(() => {
const envRefreshTime = LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS_ENV;
Expand All @@ -29,19 +21,17 @@ export const ProtectedRoute = ({ children }) => {
: envRefreshTime;

const intervalFunction = () => {
if (isAuthenticated) {
mutateRefresh({ refresh_token: refreshToken });
}
mutateRefresh();
};

const intervalId = setInterval(intervalFunction, accessTokenTimer * 1000);
intervalFunction();

return () => clearInterval(intervalId);
if (!autoLogin && isAuthenticated) {
const intervalId = setInterval(intervalFunction, accessTokenTimer * 1000);
intervalFunction();
return () => clearInterval(intervalId);
}
}, [isAuthenticated]);

if (!isAuthenticated && hasToken) {
mutationLogout();
if (!isAuthenticated && !autoLogin) {
return <CustomNavigate to="/login" replace />;
} else {
return children;
}
Expand Down
25 changes: 11 additions & 14 deletions src/frontend/src/controllers/API/api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,21 +145,18 @@ function ApiInterceptor() {
error.config.headers[key] = value;
}
}
mutationRenewAccessToken(
{},
{
onSuccess: async (data) => {
authenticationErrorCount = 0;
await remakeRequest(error);
authenticationErrorCount = 0;
},
onError: (error) => {
console.error(error);
mutationLogout();
return Promise.reject("Authentication error");
},
mutationRenewAccessToken(undefined, {
onSuccess: async () => {
authenticationErrorCount = 0;
await remakeRequest(error);
authenticationErrorCount = 0;
},
);
onError: (error) => {
console.error(error);
mutationLogout();
return Promise.reject("Authentication error");
},
});
}

async function clearBuildVerticesState(error) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AuthContext } from "@/contexts/authContext";
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
import useAuthStore from "@/stores/authStore";
import { AxiosError } from "axios";
import { useContext } from "react";
Expand All @@ -23,7 +24,8 @@ export const useGetAutoLogin: useQueryFunctionType<undefined, undefined> = (
const setAutoLogin = useAuthStore((state) => state.setAutoLogin);
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
const isLoginPage = location.pathname.includes("login");
const { mutate: mutationLogout } = useLogout();
const navigate = useCustomNavigate();
const { mutateAsync: mutationLogout } = useLogout();

async function getAutoLoginFn(): Promise<null> {
try {
Expand All @@ -41,8 +43,8 @@ export const useGetAutoLogin: useQueryFunctionType<undefined, undefined> = (
setAutoLogin(false);
if (!isLoginPage) {
if (!isAuthenticated) {
mutationLogout();
throw new Error("Unauthorized");
await mutationLogout();
navigate("/login");
} else {
getUser();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { keepPreviousData, UseMutationResult } from "@tanstack/react-query";
import {
useMutationFunctionType,
useQueryFunctionType,
Users,
} from "../../../../types/api";
import { UseMutationResult } from "@tanstack/react-query";
import { useMutationFunctionType, Users } from "../../../../types/api";
import { api } from "../../api";
import { getURL } from "../../helpers/constants";
import { UseRequestProcessor } from "../../services/request-processor";
Expand Down Expand Up @@ -35,7 +31,7 @@ export const useGetUsers: useMutationFunctionType<any, getUsersQueryParams> = (
getUsersQueryParams,
any,
getUsersQueryParams
> = mutate(["useRefreshAccessToken"], getUsers, options);
> = mutate(["useGetUsers"], getUsers, options);

return mutation;
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import useAuthStore from "@/stores/authStore";
import { useMutationFunctionType } from "@/types/api";

import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
import { api } from "../../api";
import { getURL } from "../../helpers/constants";
import { UseRequestProcessor } from "../../services/request-processor";
Expand All @@ -10,7 +9,6 @@ export const useLogout: useMutationFunctionType<undefined, void> = (
options?,
) => {
const { mutate } = UseRequestProcessor();
const navigate = useCustomNavigate();
const logout = useAuthStore((state) => state.logout);

async function logoutUser(): Promise<any> {
Expand All @@ -25,7 +23,6 @@ export const useLogout: useMutationFunctionType<undefined, void> = (
const mutation = mutate(["useLogout"], logoutUser, {
onSuccess: () => {
logout();
navigate("/login");
},
onError: (error) => {
console.error(error);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
import { LoginType, changeUser, useMutationFunctionType } from "@/types/api";
import { UseMutationResult } from "@tanstack/react-query";
import { LANGFLOW_REFRESH_TOKEN } from "@/constants/constants";
import { useMutationFunctionType } from "@/types/api";
import { Cookies } from "react-cookie";
import { api } from "../../api";
import { getURL } from "../../helpers/constants";
import { UseRequestProcessor } from "../../services/request-processor";
interface IRefreshAccessToken {
access_token: string;
refresh_token: string;
token_type: string;
}

export const useRefreshAccessToken: useMutationFunctionType<undefined, any> = (
options?,
) => {
export const useRefreshAccessToken: useMutationFunctionType<
undefined,
undefined | void,
IRefreshAccessToken
> = (options?) => {
const { mutate } = UseRequestProcessor();
const cookies = new Cookies();

async function refreshAccess(): Promise<IRefreshAccessToken> {
const res = await api.post<IRefreshAccessToken>(`${getURL("REFRESH")}`);
cookies.set(LANGFLOW_REFRESH_TOKEN, res.data.refresh_token, { path: "/" });

async function refreshAccess(): Promise<any> {
const res = await api.post(`${getURL("REFRESH")}`);
return res.data;
}

const mutation: UseMutationResult = mutate(
["useRefreshAccessToken"],
refreshAccess,
options,
);
const mutation = mutate(["useRefreshAccessToken"], refreshAccess, options);

return mutation;
};
1 change: 0 additions & 1 deletion src/frontend/src/modals/userManagementModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export default function UserManagementModal({
}: inputHandlerEventType): void {
setInputState((prev) => ({ ...prev, [name]: value }));
}
console.log(data);

useEffect(() => {
if (open) {
Expand Down
Loading