In-memory JWT setup #1178
-
Hello! My goal is to follow this architecture (Hasura ref), which I would summarize as:
My current issue is that I'm using React state to keep track of my JWT and it appears that my urql client is being initialized twice. This makes me believe that the re-renders due to the state are re-initializing my client, triggering my My function App() {
const history = useHistory();
const { pathname } = useLocation();
const [token, setToken] = useState(null);
const [tokenExpiry, setTokenExpiry] = useState(null);
const [hasInit, setHasInit] = useState(localStorage.getItem('hasLoggedIn') !== 'yes')
const client = useMemo(() => {
return createClient({
url: GRAPHQL_API,
exchanges: [
devtoolsExchange,
dedupExchange,
cacheExchange,
authExchange({
getAuth: async ({ authState }) => {
if (!authState) {
if (token) {
console.log("HERE (1) - token:", token.slice(-6));
return { token };
}
if (!hasInit) {
console.log("HERE (2) - INIT:", hasInit);
const { ok, ...data } = await getTokenFromRefresh();
console.log('REFRESH CALLED. TOKEN ->', data.token.slice(-6))
if (ok) {
setToken(data.token);
setTokenExpiry(data.tokenExpiry);
setHasInit(true);
return { token: data.token }
}
}
return null;
}
const { ok, ...data } = await getTokenFromRefresh();
if (ok) {
setToken(data.token);
setTokenExpiry(data.tokenExpiry);
return { token: data.token }
}
// --- LOGOUT BLOCK ---
const isAuthOnlyPath = authOnlyPaths.find(({ path, exact, strict }) => matchPath(pathname, {
path,
exact,
strict
}));
// remove refresh token cookie
await axios.post(AUTH_API + '/logout', { withCredentials: true });
// to support logging out from all windows
window.localStorage.setItem('logout', Date.now());
window.localStorage.clear();
setToken(null);
setTokenExpiry(null);
if (isAuthOnlyPath) {
history.replace('/login');
}
return null;
},
addAuthToOperation,
didAuthError: ({ error }) => {
const hasError = error.graphQLErrors.some(e => e.extensions?.code === 'invalid-jwt');
console.log("HERE (4) - auth error:", error.graphQLErrors, hasError);
return hasError;
},
}),
fetchExchange,
],
})
}, []);
return (
<UrqlProvider value={client}>
<UserProvider authOnlyPaths={authOnlyPaths} setToken={setToken} setTokenExpiry={setTokenExpiry} token={token}>
<Switch>
{/* Routes here */}
</Switch>
</UserProvider>
</UrqlProvider>
);
}
export default App; Note I'm trying to use
I've almost given up on this setup and have another implementation using the traditional Thanks for any ideas and help 😃 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 5 replies
-
The reason your client is created twice would be |
Beta Was this translation helpful? Give feedback.
The reason your client is created twice would be
StrictMode
, the token-refresh gets called twice because you are calling it eagerly in yourgetAuth
function, it seems better to only refresh your token when an error occurs or when you're sure that the token has expired.