Authenticated now working properly

Hello, I have my app setup as follows:
<Routes>
<Route path="/register" element={<RegisterPage />} />
<Route path="/login" element={<LoginPage />} />
<Route
path="/forgot-password"
element={<ForgotPasswordPage />}
/>
<Route
path="/update-password"
element={<UpdatePasswordPage />}
/>
<Route
element={
<Authenticated
key="authenticated-layout"
fallback={<CatchAllNavigate to="/login" />}
>
<Layout>
<Outlet />
</Layout>
</Authenticated>
}
>
<Route index element={<Home />} />
<Route path="/customers">
<Route index element={<CustomerList />} />
<Route path="new" element={<CreateCustomer />} />
</Route>
<Route path="/events">
<Route index element={<EventList />} />
<Route path="new" element={<CreateEvent />} />
</Route>
</Route>
</Routes>
<Routes>
<Route path="/register" element={<RegisterPage />} />
<Route path="/login" element={<LoginPage />} />
<Route
path="/forgot-password"
element={<ForgotPasswordPage />}
/>
<Route
path="/update-password"
element={<UpdatePasswordPage />}
/>
<Route
element={
<Authenticated
key="authenticated-layout"
fallback={<CatchAllNavigate to="/login" />}
>
<Layout>
<Outlet />
</Layout>
</Authenticated>
}
>
<Route index element={<Home />} />
<Route path="/customers">
<Route index element={<CustomerList />} />
<Route path="new" element={<CreateCustomer />} />
</Route>
<Route path="/events">
<Route index element={<EventList />} />
<Route path="new" element={<CreateEvent />} />
</Route>
</Route>
</Routes>
However if I stay for example on /events/list page and wait for accessToken to expire and then navigate to /costumers page the data doesn't load because I'm no longer authenticated but <Authenticated /> component doesn't call check when I navigate from /events to /customers. How do I resolve this issue? Calling useIsAuthenticated hook goes into infinite render loop
kapa.ai
kapa.ai82d ago
Hi @chachi. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Hmm, I don't know enough to give you a confident answer yet. However, for handling authentication and ensuring that your <Authenticated /> component reacts appropriately to changes in authentication status, you might want to review the documentation and examples provided by refine for best practices and troubleshooting tips. Specifically, looking into how the authProvider is implemented and ensuring it correctly handles session expiration and token renewal could be beneficial. Additionally, exploring the use of context or state management to trigger re-authentication checks across route changes might help resolve the issue you're facing. For more detailed guidance and examples on implementing authentication with refine, including the use of <Authenticated /> component and authProvider, you can refer to the official documentation here: Refine Docs on Authentication (https://refine.dev/docs/). Since the extracts provided do not contain a direct solution to the issue of the <Authenticated /> component not re-checking authentication status on route changes, I recommend exploring the documentation and community discussions for insights and potential workarounds that have worked for others in similar situations. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai82d ago
<@95552725294518272> kapa.ai is still learning and improving, please let us know how it did by reacting below
exotic-emerald
exotic-emerald82d ago
Hello @chachi, can you share your auth provider with us?
fair-rose
fair-rose82d ago
Hey @Alican Erdurmaz, sure, here is my check function:
check: async () => {
try {
const accessToken = localStorage.getItem('accessToken');
if (!accessToken) {
return {
authenticated: false,
redirectTo: '/login',
};
}

const checkResponse = await fetch(AUTH_API_BASE_URL + '/check', {
method: 'GET',
cache: 'no-cache',
mode: 'cors',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
});

if (checkResponse.status === 200) {
const resJson = await checkResponse.json();
sessionStorage.setItem('id', resJson.id);

return {
authenticated: true,
redirectTo: '/',
};
}

if (checkResponse.status === 401) {
const refreshResponse = await fetch(AUTH_API_BASE_URL + '/refresh', {
method: 'GET',
cache: 'no-cache',
mode: 'cors',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
});

if (refreshResponse.status === 200) {
const resJson = await refreshResponse.json();
localStorage.setItem('accessToken', resJson.accessToken);

return {
authenticated: true,
redirectTo: '/',
};
}
}
return {
authenticated: false,
redirectTo: '/login',
};
} catch (e) {
const error = e as Error;

return {
authenticated: false,
redirectTo: '/login',
error: error,
};
}
},
check: async () => {
try {
const accessToken = localStorage.getItem('accessToken');
if (!accessToken) {
return {
authenticated: false,
redirectTo: '/login',
};
}

const checkResponse = await fetch(AUTH_API_BASE_URL + '/check', {
method: 'GET',
cache: 'no-cache',
mode: 'cors',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
});

if (checkResponse.status === 200) {
const resJson = await checkResponse.json();
sessionStorage.setItem('id', resJson.id);

return {
authenticated: true,
redirectTo: '/',
};
}

if (checkResponse.status === 401) {
const refreshResponse = await fetch(AUTH_API_BASE_URL + '/refresh', {
method: 'GET',
cache: 'no-cache',
mode: 'cors',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
});

if (refreshResponse.status === 200) {
const resJson = await refreshResponse.json();
localStorage.setItem('accessToken', resJson.accessToken);

return {
authenticated: true,
redirectTo: '/',
};
}
}
return {
authenticated: false,
redirectTo: '/login',
};
} catch (e) {
const error = e as Error;

return {
authenticated: false,
redirectTo: '/login',
error: error,
};
}
},
And here the whole authProvider:
exotic-emerald
exotic-emerald74d ago
Code seems okay, I need time to debug. thanks for sharing issue with us Hello again @chachi, Sorry for late response. <Authenticted /> component not sent request on every route change (not calling authProvider.check), you can use authProvider.onError component and after API returns 403 you can logout your user and redirect to login page
fair-rose
fair-rose64d ago
@Alican Erdurmaz Even when the user is just navigating between resources the Authenticated component doesn't call the check method but that doesn't mean the user is inactive. I don't want to logout the user every 30 minutes (expiration of my accessToken) because of this. So I'm guessing the only solution is to use useIsAuthenticated on every page that requires being authenticated?
exotic-emerald
exotic-emerald63d ago
Yes you can use useIsAuthenticated but, I believe using authProvider.onError is the best practice to handle this kind of use cases. When the API returns 401 or 403, you can logout the user in the onError method, so you don't need to request the API on every page transition
More Posts
onFinish, being sent as object instead of inputI'm using onFinish to pass input, but it's being sent as an object, how can i change this?Distinct TableHow can I setup my table to only show the first occurrence of a record, e.g. distinct value? ``` <Tfilters in url routeI am loading my default route for a table, however the filters are being added in the url route by dNo application ConnectedWhen i create a new refine project using npm create refine-app@latest ..and a followed all the stepsglobal state and contexti couldn't find anything on documentation regarding global state management and contexts. is there aString filtering on tableAntdesign table, search for sub-string within returned value and display in tableSubstring FilterIs there a way to search a filter and match all records including a sub-string, e.g. searching 703 waccess control cachingHi, the caching of access control provider does not seem to work. The caching in general works (for Auto refresh supabase tokenI'm using a supabase auth provider (with remix). Shouldn't it automatically refresh a user session texamples not workingnpm create refine-app@latest -- --example app-crm / CRUD apps so sleek, even the cows \ | want in!Multiple fields as label for Ant Design's selectBased on a question in this channel titled `using multiple fields for the label in select ant designRoot access with CasbinI'm running on a standard React with Supabase build. I have Casbin set up with 3 user roles (superAdCall check when changing resourcesWhen I am inactive for more than 10 minutes and the access token expires and then I click in the menTrigger built in notificationsHow can I show a notification using the built in notification snackbars? Is there any method I can urefine muii am getting this error when i am trying to use the materialui notificationprovider Error: Objects Hasura dataprovider : How to query with _not operator ?How can i query data with _not operator like this `query query { event(where: {_not: {group_evenHow would I integrate table filters into this?import React from "react"; import { IResourceComponentsProps, BaseRecord } from "@refinedev/core"; iFilter nested fieldsI use hasura dataprovider, and i wonder how to use nested filter in order to apply filter on nested Does refine supabase support functions?I need to updated multiple tables one of them has many-to-many relationship in the same edit. Does rUser managementHow can I manage users, edit, delete & add them via postgreSQL