-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Open
Labels
Description
I have implemented the reauthorization process with RTK Query following the docs:
This is api.ts a single createApi instance in the app:
import { createApi } from '@reduxjs/toolkit/query/react';
import { baseQueryWithReauth } from './utils';
export const api = createApi({
reducerPath: 'api',
baseQuery: baseQueryWithReauth,
endpoints: (builder) => ({}),
});
And this is what i followed, the only thing that differs is
import { fetchBaseQuery } from '@reduxjs/toolkit/query'
import type {
BaseQueryFn,
FetchArgs,
FetchBaseQueryError,
} from '@reduxjs/toolkit/query'
import { tokenReceived, loggedOut } from './authSlice'
import { Mutex } from 'async-mutex'
// create a new mutex
const mutex = new Mutex();
const baseQuery =
fetchBaseQuery({
baseUrl: `${process.env.BASE_URL}`,
prepareHeaders: (headers: Headers) => generateHeadersIfAny(headers),
}),
const baseQueryWithReauth: BaseQueryFn<
string | FetchArgs,
unknown,
FetchBaseQueryError
> = async (args, api, extraOptions) => {
// wait until the mutex is available without locking it
await mutex.waitForUnlock()
let result = await baseQuery(args, api, extraOptions)
if (result.error && result.error.status === 401) {
// checking whether the mutex is locked
if (!mutex.isLocked()) {
const release = await mutex.acquire()
try {
const refreshResult = await baseQuery(
'/get-new-tokens',
api,
extraOptions
)
if (refreshResult.data) {
api.dispatch(tokenReceived(refreshResult.data))
// retry the initial query
result = await baseQuery(args, api, extraOptions)
} else {
api.dispatch(loggedOut())
}
} finally {
// release must be called once the mutex should be released again.
release()
}
} else {
// wait until the mutex is available without locking it
await mutex.waitForUnlock()
result = await baseQuery(args, api, extraOptions)
}
}
return result
}
And this example works perfectly when refresh token did not expire and your refetch route returns 200 and new tokens, but the problem is when your refresh route returns 401 or 400 it goes in the else of if/else but it reruns all the requests that got 401. It's like it only works in the most optimistic case. I would like if my get-new-tokens route returns 400 or 401 don't rerun any of the multiple requests you have in mutex.
allybee
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
smyja commentedon Nov 5, 2023
did you resolve this?
herarya commentedon Nov 6, 2023
same issue here, follow the doc, after refresh token, need to set to redux first and continue the api call
allybee commentedon Mar 19, 2024
It seems to work as documented with async-mutex@v0.4.1, but is broken in async-mutex@v0.5.0.
AlexeyEsin commentedon Aug 21, 2024
I had the same problem, and I solved it by adding a query restart condition. Since I store the authorization status in the redux slice, I can set it to false in the
loggedOut
function and restart the request only if the status is set to true. Here's what it looks like:Also, if you store the refresh token in localStorage, you can clear it in
loggedOut
and check for its presence when restarting the query.It might be worth adding this to the documentation.