refactor: switch to HttpOnly cookie (#660)

* Switch to httpOnly cookie
* create endpoint to retrieve temporary collaboration token

* cleanups
This commit is contained in:
Philip Okugbe
2025-01-22 22:11:11 +00:00
committed by GitHub
parent f2235fd2a2
commit 990612793f
29 changed files with 240 additions and 276 deletions
+12 -52
View File
@@ -2,13 +2,13 @@ import { useState } from "react";
import {
forgotPassword,
login,
logout,
passwordReset,
setupWorkspace,
verifyUserToken,
} from "@/features/auth/services/auth-service";
import { useNavigate } from "react-router-dom";
import { useAtom } from "jotai";
import { authTokensAtom } from "@/features/auth/atoms/auth-tokens-atom";
import { currentUserAtom } from "@/features/user/atoms/current-user-atom";
import {
IForgotPassword,
@@ -20,31 +20,26 @@ import {
import { notifications } from "@mantine/notifications";
import { IAcceptInvite } from "@/features/workspace/types/workspace.types.ts";
import { acceptInvitation } from "@/features/workspace/services/workspace-service.ts";
import Cookies from "js-cookie";
import { jwtDecode } from "jwt-decode";
import APP_ROUTE from "@/lib/app-route.ts";
import { useQueryClient } from "@tanstack/react-query";
import { RESET } from "jotai/utils";
import { useTranslation } from "react-i18next";
export default function useAuth() {
const { t } = useTranslation();
const [isLoading, setIsLoading] = useState(false);
const navigate = useNavigate();
const [, setCurrentUser] = useAtom(currentUserAtom);
const [authToken, setAuthToken] = useAtom(authTokensAtom);
const queryClient = useQueryClient();
const handleSignIn = async (data: ILogin) => {
setIsLoading(true);
try {
const res = await login(data);
await login(data);
setIsLoading(false);
setAuthToken(res.tokens);
navigate(APP_ROUTE.HOME);
} catch (err) {
console.log(err);
setIsLoading(false);
console.log(err);
notifications.show({
message: err.response?.data.message,
color: "red",
@@ -56,11 +51,8 @@ export default function useAuth() {
setIsLoading(true);
try {
const res = await acceptInvitation(data);
await acceptInvitation(data);
setIsLoading(false);
setAuthToken(res.tokens);
navigate(APP_ROUTE.HOME);
} catch (err) {
setIsLoading(false);
@@ -77,9 +69,6 @@ export default function useAuth() {
try {
const res = await setupWorkspace(data);
setIsLoading(false);
setAuthToken(res.tokens);
navigate(APP_ROUTE.HOME);
} catch (err) {
setIsLoading(false);
@@ -94,14 +83,11 @@ export default function useAuth() {
setIsLoading(true);
try {
const res = await passwordReset(data);
await passwordReset(data);
setIsLoading(false);
setAuthToken(res.tokens);
navigate(APP_ROUTE.HOME);
notifications.show({
message: "Password reset was successful",
message: t("Password reset was successful"),
});
} catch (err) {
setIsLoading(false);
@@ -112,34 +98,10 @@ export default function useAuth() {
}
};
const handleIsAuthenticated = async () => {
if (!authToken) {
return false;
}
try {
const accessToken = authToken.accessToken;
const payload = jwtDecode(accessToken);
// true if jwt is active
const now = Date.now().valueOf() / 1000;
return payload.exp >= now;
} catch (err) {
console.log("invalid jwt token", err);
return false;
}
};
const hasTokens = (): boolean => {
return !!authToken;
};
const handleLogout = async () => {
setAuthToken(null);
setCurrentUser(null);
Cookies.remove("authTokens");
queryClient.clear();
window.location.replace(APP_ROUTE.AUTH.LOGIN);;
setCurrentUser(RESET);
await logout();
window.location.replace(APP_ROUTE.AUTH.LOGIN);
};
const handleForgotPassword = async (data: IForgotPassword) => {
@@ -182,12 +144,10 @@ export default function useAuth() {
signIn: handleSignIn,
invitationSignup: handleInvitationSignUp,
setupWorkspace: handleSetupWorkspace,
isAuthenticated: handleIsAuthenticated,
forgotPassword: handleForgotPassword,
passwordReset: handlePasswordReset,
verifyUserToken: handleVerifyUserToken,
logout: handleLogout,
hasTokens,
isLoading,
};
}