Skip to content

Commit

Permalink
🐛(sso) prevent flash when trying to autologin
Browse files Browse the repository at this point in the history
the issue was we return the fetchUser promise to react query too early
(before the browser reloaded the page). now we make sure react query
doesn't get the info
  • Loading branch information
manuhabitela committed Jul 25, 2024
1 parent d3ef15b commit ed1581d
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 12 deletions.
11 changes: 8 additions & 3 deletions src/frontend/src/features/auth/api/fetchUser.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ApiError } from '@/api/ApiError'
import { fetchApi } from '@/api/fetchApi'
import { type ApiUser } from './ApiUser'
import { attemptSilentLogin } from "@/features/auth";
import { attemptSilentLogin, canAttemptSilentLogin } from '../utils/silentLogin'

/**
* fetch the logged-in user from the api.
Expand All @@ -17,8 +17,13 @@ export const fetchUser = (): Promise<ApiUser | false> => {
.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)
// make sure to not resolve the promise while trying to silent login
// so that consumers of fetchUser don't think the work already ended
if (canAttemptSilentLogin()) {
attemptSilentLogin(3600)
} else {
resolve(false)
}
} else {
reject(error)
}
Expand Down
12 changes: 6 additions & 6 deletions src/frontend/src/features/auth/api/useUser.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useQuery } from '@tanstack/react-query'
import { keys } from '@/api/queryKeys'
import { fetchUser } from './fetchUser'
import { type ApiUser } from './ApiUser'

/**
* returns info about currently logged in user
Expand All @@ -13,14 +14,13 @@ export const useUser = () => {
queryFn: fetchUser,
})

let isLoggedIn = undefined
if (query.data !== undefined) {
isLoggedIn = query.data !== false
}
const isLoggedIn =
query.status === 'success' ? query.data !== false : undefined
const isLoggedOut = isLoggedIn === false

return {
...query,
// if fetchUser returns false, it means the user is not logged in: expose that
user: query.data === false ? undefined : query.data,
user: isLoggedOut ? undefined : (query.data as ApiUser | undefined),
isLoggedIn,
}
}
1 change: 0 additions & 1 deletion src/frontend/src/features/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@ 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'
5 changes: 4 additions & 1 deletion src/frontend/src/features/auth/utils/authUrl.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { apiUrl } from '@/api/apiUrl'

export const authUrl = (silent = false, returnTo = window.location.href) => {
export const authUrl = ({
silent = false,
returnTo = window.location.href,
} = {}) => {
return apiUrl(`/authenticate?silent=${encodeURIComponent(silent)}&returnTo=${encodeURIComponent(returnTo)}`)
}
6 changes: 5 additions & 1 deletion src/frontend/src/features/auth/utils/silentLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ const setNextRetryTime = (retryIntervalInSeconds: number) => {
}

const initiateSilentLogin = () => {
window.location.href = authUrl(true)
window.location.href = authUrl({ silent: true })
}

export const canAttemptSilentLogin = () => {
return isRetryAllowed()
}

export const attemptSilentLogin = (retryIntervalInSeconds: number) => {
Expand Down

0 comments on commit ed1581d

Please sign in to comment.