This is an authorizaton middleware component that wraps the App component in a React app using Redux Toolkit.
The authorization is done using an access_token cookie. There is a also a logged_in cookie with httponly=false so the client knows its logged in, and a refresh_token cookie.
The logic is:
-
- check if there is a
logged_incookie, if not, finish
- check if there is a
-
- send a request to the
GetWhoAmIapi endpoint
GetWhoAmIsuccess: finish
- send a request to the
-
GetWhoAmIfail: try to refresh theaccess_tokenusing theRefreshTokenendpoint
RefreshTokenfail: delete thelogged_incookie and finish
-
RefreshTokensuccess: try theGetWhoAmIendpoint again
GetWhoAmIsuccess: finishGetWhoAmIfail: removelogged_incookie and finish
I do not like this state machine approach, but I have tried everything else and I kept getting strange loops, or queries not running at all.
export const AuthMiddleware: React.FC<{ children: React.ReactElement }> =
({ children }) => {
const [state, setState] = useState(1);
const [cookie, , removeCookie] = useCookies(["logged_in"]);
const hasLoggedInCookie = cookie.logged_in === "true";
const { isSuccess: whoAmISuccess, isError: whoAmIError } =
useGetWhoAmIQuery(undefined, { skip: state !== 2 && state !== 4 });
const { isSuccess: refreshSuccess, isError: refreshError } =
useRefreshTokenQuery(undefined, { skip: state !== 3 });
if (state === 1) {
setState(hasLoggedInCookie ? 2 : 0);
}
if (state === 2 && whoAmIError) setState(3);
if (state === 2 && whoAmISuccess) setState(0);
if (state === 4 && whoAmISuccess) setState(0);
if (state === 4 && whoAmIError) {
removeCookie("logged_in");
setState(0);
}
if (state === 3 && refreshError) {
removeCookie("logged_in");
setState(0);
}
if (state === 3 && refreshSuccess) {
setState(4);
}
console.log(state);
if (state !== 0) {
return <FullScreenLoader />;
}
return children;
};
As far as functionality goes this works, but there are two strange issues:
- When it gets to the point where the
RefreshTokenendpoint needs to be invoked, the endpoint is queried twice in a row.
- If I log the state, it looks as the state goes backwards sometime, for example it goes 3-2-3 or 4-3-4, even though from the code it is not possible for the state to go from 4 to 3 or from 3 to 2.
There is obviously something I'm doing wrong here but after two days of banging my head against this problem I can't figure it out.