Skip to content
This repository has been archived by the owner on Sep 17, 2024. It is now read-only.

Commit

Permalink
fix(Auth): get current user on root instead of topbar to avoid sync i…
Browse files Browse the repository at this point in the history
…ssue with refresh token timeout.

Signed-off-by: reslene <reslene@numary.com>
  • Loading branch information
reslene committed May 2, 2023
1 parent 4e85cc0 commit c6116a7
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 37 deletions.
29 changes: 17 additions & 12 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,13 @@ import { getRoute, OVERVIEW_ROUTE } from '~/src/components/Layout/routes';
import ClientStyleContext from '~/src/contexts/clientStyleContext';
import { ServiceContext } from '~/src/contexts/service';
import { Errors } from '~/src/types/generic';
import {
Authentication,
CurrentUser,
errorsMap,
logger,
} from '~/src/utils/api';
import { Authentication, errorsMap, logger } from '~/src/utils/api';
import { ReactApiClient } from '~/src/utils/api.client';
import {
AUTH_CALLBACK_ROUTE,
COOKIE_NAME,
decrypt,
getCurrentUser,
getJwtPayload,
getOpenIdConfig,
getSession,
Expand Down Expand Up @@ -93,16 +89,27 @@ export const loader: LoaderFunction = async ({ request }) => {
await withSession(request, async () => {
const sessionHolder = decrypt<Authentication>(cookie);
const payload = getJwtPayload(sessionHolder);
const user = await getCurrentUser(
openIdConfig,
sessionHolder.access_token
);

const pseudo = user && user.email ? user.email.split('@')[0] : undefined;

const currentUser = {
...user,
avatarLetter: pseudo ? pseudo.split('')[0].toUpperCase() : undefined,
scp: payload ? payload.scp : [],
pseudo,
};

return {
metas: {
origin: REDIRECT_URI,
openIdConfig,
api: process.env.API_URL,
},
currentUser: {
scp: payload ? payload.scp : [],
},
currentUser,
};
})
);
Expand Down Expand Up @@ -267,7 +274,6 @@ const Document = withEmotionCache(
// https://remix.run/api/conventions#route-filenames
export default function App() {
const { metas, currentUser } = useLoaderData();
const [user, setUser] = useState<CurrentUser>(currentUser);
const { t } = useTranslation();
const [loading, _load, stopLoading] = useOpen(true);
const [feedback, setFeedback] = useState({
Expand Down Expand Up @@ -331,8 +337,7 @@ export default function App() {
<ServiceContext.Provider
value={{
api: new ReactApiClient(),
currentUser: user,
setCurrentUser: (user: CurrentUser) => setUser(user),
currentUser,
metas,
snackbar: displayFeedback,
}}
Expand Down
24 changes: 1 addition & 23 deletions app/src/components/Layout/components/Topbar/Topbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,14 @@ import Search from '~/src/components/Search';
import { useService } from '~/src/hooks/useService';
import useSimpleMediaQuery from '~/src/hooks/useSimpleMediaQuery';
import { Gateway } from '~/src/types/gateway';
import { CurrentUser } from '~/src/utils/api';
import { ReactApiClient } from '~/src/utils/api.client';

const Topbar: FunctionComponent<TopbarProps> = ({ resized, onResize }) => {
const { palette } = useTheme();
const { t } = useTranslation();
const { isMobile } = useSimpleMediaQuery();
const [gateway, setGateway] = useState<{ region: string; env: string }>();
const { api, setCurrentUser, currentUser, metas } = useService();
const { currentUser, metas } = useService();
const [anchorElUser, setAnchorElUser] = React.useState<null | HTMLElement>(
null
);
Expand Down Expand Up @@ -73,26 +72,6 @@ const Topbar: FunctionComponent<TopbarProps> = ({ resized, onResize }) => {
window.location.href = `${metas.origin}/auth/redirect-logout`;
};

const getCurrentUser = async () => {
try {
const user = await api.getResource<CurrentUser>(
`${metas.openIdConfig.userinfo_endpoint.split('api')[1]}`
);
if (user) {
const pseudo =
user && user.email ? user.email.split('@')[0] : undefined;

setCurrentUser({
...user,
avatarLetter: pseudo ? pseudo.split('')[0].toUpperCase() : undefined,
pseudo,
});
}
} catch (e) {
console.info('Current user could not be retrieved yet');
}
};

useEffect(() => {
(async () => {
const client = new ReactApiClient();
Expand All @@ -101,7 +80,6 @@ const Topbar: FunctionComponent<TopbarProps> = ({ resized, onResize }) => {
if (gateway) {
setGateway(gateway);
}
await getCurrentUser();
})();
}, []);

Expand Down
2 changes: 0 additions & 2 deletions app/src/contexts/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ import { ApiClient, CurrentUser } from '~/src/utils/api';
import { OpenIdConfiguration } from '~/src/utils/auth.server';

export type SnackbarSetter = (message?: string) => void;
export type SetCurrentUser = (_user: CurrentUser) => void;

export type ServiceContext = {
api: ApiClient;
currentUser: CurrentUser;
setCurrentUser: SetCurrentUser;
metas: {
origin: string;
openIdConfig: OpenIdConfiguration;
Expand Down
13 changes: 13 additions & 0 deletions app/src/utils/auth.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ObjectOf } from '~/src/types/generic';
import {
API_AUTH,
Authentication,
CurrentUser,
JwtPayload,
Methods,
SessionWrapper,
Expand Down Expand Up @@ -89,6 +90,18 @@ export const getOpenIdConfig = async (): Promise<OpenIdConfiguration> => {
});
};

export const getCurrentUser = async (
openIdConfig: OpenIdConfiguration,
token: string
): Promise<CurrentUser> =>
fetch(openIdConfig.userinfo_endpoint, {
headers: { Authorization: `Bearer ${token}` },
})
.then(async (response) => response.json())
.catch(() => {
throw new Error('Error while fetching current user');
});

export const getJwtPayload = (
decryptedCookie: Authentication
): JwtPayload | undefined =>
Expand Down

0 comments on commit c6116a7

Please sign in to comment.