fix: auto login and logout functionality (#3629)

* Made auto login not call refresh

* Fixed mutation query

* Removed navigation to login on logout function

* Made refresh token set cookie for docker

* Added return to login with custom navigate and added check for refreshing only if its authenticated

* Minor refactor

* Navigate after logout on get autologin

* Removed unused console.log
This commit is contained in:
Lucas Oliveira 2024-08-30 15:19:32 -03:00 • committed by GitHub
commit a71375c6f9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 49 additions and 61 deletions

View file

@ -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;
@ -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;
}

View file

@ -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) {

View file

@ -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";
@ -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 {
@ -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();
}

View file

@ -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";
@ -35,7 +31,7 @@ export const useGetUsers: useMutationFunctionType<any, getUsersQueryParams> = (
getUsersQueryParams,
any,
getUsersQueryParams
> = mutate(["useRefreshAccessToken"], getUsers, options);
> = mutate(["useGetUsers"], getUsers, options);
return mutation;
};

View file

@ -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";
@ -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> {
@ -25,7 +23,6 @@ export const useLogout: useMutationFunctionType<undefined, void> = (
const mutation = mutate(["useLogout"], logoutUser, {
onSuccess: () => {
logout();
navigate("/login");
},
onError: (error) => {
console.error(error);

View file

@ -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;
};

View file

@ -42,7 +42,6 @@ export default function UserManagementModal({
}: inputHandlerEventType): void {
setInputState((prev) => ({ ...prev, [name]: value }));
}
console.log(data);
useEffect(() => {
if (open) {