Reputation: 1464
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:
logged_in
cookie, if not, finishGetWhoAmI
api endpointGetWhoAmI
success: finishGetWhoAmI
fail: try to refresh the access_token
using the RefreshToken
endpointRefreshToken
fail: delete the logged_in
cookie and finishRefreshToken
success: try the GetWhoAmI
endpoint againGetWhoAmI
success: finishGetWhoAmI
fail: remove logged_in
cookie and finishI 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:
RefreshToken
endpoint needs to be invoked, the endpoint is queried twice in a row.
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.
Upvotes: 1
Views: 3880
Reputation: 44086
There is a refresh token approach in the documentation that lives in RTK Query, not in a component - have you tried that?
Automatic Reauthorization by extending fetchBaseQuery
Your code would come down to a single useGetWhoAmIQuery()
call.
Also, something like a token refresh (if you choose this approach here) should always be a mutation, not a query. Then it could also invalidate the getWhoAmIQuery
and it could automatically refetch - no need for you to orchestrate that!
Upvotes: 2