From 234116163a9c6e3b65e8e88ef7e8da852d6dd8ca Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Wed, 24 Jul 2024 23:28:30 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(frontend)=20try=20silent=20login=20ev?= =?UTF-8?q?ery=20one=20hour?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is totally work in progress. @manuhabitela the floor is yours. If the user is logged-out, try silently log-in her every hour, to avoid any manual login on her side. The one hour value has been discussed with @manuhabitela, but there is no real logic behind it. Could definitely be shorter or longer. It needs at least to be longer than the average silent login flow to avoid locking the user-agent in an infinite redirection loop. --- .../src/features/auth/api/fetchUser.ts | 2 ++ src/frontend/src/features/auth/index.ts | 1 + .../src/features/auth/utils/silentLogin.ts | 30 +++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/frontend/src/features/auth/utils/silentLogin.ts diff --git a/src/frontend/src/features/auth/api/fetchUser.ts b/src/frontend/src/features/auth/api/fetchUser.ts index 512b3d02..aa7031cc 100644 --- a/src/frontend/src/features/auth/api/fetchUser.ts +++ b/src/frontend/src/features/auth/api/fetchUser.ts @@ -1,6 +1,7 @@ import { ApiError } from '@/api/ApiError' import { fetchApi } from '@/api/fetchApi' import { type ApiUser } from './ApiUser' +import { attemptSilentLogin } from "@/features/auth"; /** * fetch the logged-in user from the api. @@ -16,6 +17,7 @@ export const fetchUser = (): Promise => { .catch((error) => { // we assume that a 401 means the user is not logged in if (error instanceof ApiError && error.statusCode === 401) { + attemptSilentLogin(3600) resolve(false) } else { reject(error) diff --git a/src/frontend/src/features/auth/index.ts b/src/frontend/src/features/auth/index.ts index 0b533fea..0a597d74 100644 --- a/src/frontend/src/features/auth/index.ts +++ b/src/frontend/src/features/auth/index.ts @@ -2,3 +2,4 @@ export { useUser } from './api/useUser' export { authUrl } from './utils/authUrl' export { logoutUrl } from './utils/logoutUrl' export { RenderIfUserFetched } from './components/RenderIfUserFetched' +export { attemptSilentLogin } from './utils/silentLogin' diff --git a/src/frontend/src/features/auth/utils/silentLogin.ts b/src/frontend/src/features/auth/utils/silentLogin.ts new file mode 100644 index 00000000..c301480b --- /dev/null +++ b/src/frontend/src/features/auth/utils/silentLogin.ts @@ -0,0 +1,30 @@ +import { authUrl } from "@/features/auth"; + +const SILENT_LOGIN_RETRY_KEY = 'silent-login-retry' + +const isRetryAllowed = () => { + const lastRetryDate = localStorage.getItem(SILENT_LOGIN_RETRY_KEY); + if (!lastRetryDate) { + return true; + } + const now = new Date(); + return now.getTime() > Number(lastRetryDate) +} + +const setNextRetryTime = (retryIntervalInSeconds: number) => { + const now = new Date() + const nextRetryTime = now.getTime() + (retryIntervalInSeconds * 1000); + localStorage.setItem(SILENT_LOGIN_RETRY_KEY, String(nextRetryTime)); +} + +const initiateSilentLogin = () => { + window.location.href = authUrl(true) +} + +export const attemptSilentLogin = (retryIntervalInSeconds: number) => { + if (!isRetryAllowed()) { + return + } + setNextRetryTime(retryIntervalInSeconds) + initiateSilentLogin() +}