In my React Native software, I get an entry token and a refresh token after login.
There’s a widespread operate to name the entry token once more utilizing the refresh token when the entry token is invalid
On my house web page, there are 6 APIs, however when the entry token will get invalid these 6 APIs parallelly name to the widespread operate and refresh the entry token. That is making that particular consumer get blocked.
The best way to forestall this? blocking the remainder of the APIs with a flag when the primary API’s token turns into invalid just isn’t an choice as a result of, earlier than the primary response, all of the APIs could have refreshed the entry token.
The handleResponse
operate will get triggered first then the code reaches getNewToken
funtions then it reaches the dispatch(logout());
as a result of the decision for accesstoken doesn’t develop into success and the app crashes as a result of logout is named a number of instances.
const handleResponse = async (
res: ApiResponse<BaseResponseProp, BaseResponseProp> | null,
) => {
if (res?.knowledge?.error === 'invalid_token') {
let tokenVal;
strive {
if (token.refresh_token) {
tokenVal = await getNewToken(token.refresh_token);
} else {
//refresh the general public token
tokenVal = await refreshPublicToken();
}
if (tokenVal?.access_token && tokenVal?.access_token.size > 0) {
const newTokenHeader = {
Authorization: `Bearer ${tokenVal.access_token}`,
};
invoke({
requestHeader: { ...requestHeader, ...newTokenHeader },
requestBody,
requestParams,
requestQuery,
url: formattedEndpoint,
onResultCallback,
onErrorCallback,
});
dispatch(setToken(tokenVal));
} else {
setInvalidToken(true);
navigation.dispatch(
StackActions.change(NAVIGATION_SCREENS.ROOT),
);
return;
}
return;
} catch (e) {
const newToken = await refreshPublicToken();
dispatch(setToken(newToken));
return;
}
}
const err = new CustomError(
res?.knowledge?.error || res?.originalError?.message,
res?.knowledge?.standing || 200,
);
if (typeof onErrorCallback === 'operate') {
onErrorCallback(err);
} else if (typeof onError === 'operate') {
onError(err as CustomError);
}
handleParseError(err);
} else {
const responseData = res?.knowledge as unknown as R;
if (renderData) {
setData(res?.knowledge);
}
if (typeof onResultCallback === 'operate') {
onResultCallback(res?.knowledge as unknown as R);
} else if (typeof onResult === 'operate') {
onResult(res?.knowledge);
}
}
};
const getNewToken = async (refToken: string) => {
let formattedEndpoint = ENDPOINT.LOGIN;
let tokenVal = {};
const header = { refresh_token: refToken };
const requestQuery = {
...REFRESH_AUTH_HEADERS,
...header,
};
const queryParams = new URLSearchParams({
...requestQuery,
}).toString();
formattedEndpoint = `${formattedEndpoint}?${queryParams}`;
const refreshResponse = await api.put up<LoginSuccess>(
formattedEndpoint,
{},
{
headers: basicAuthHeaders,
},
);
if (refreshResponse.standing === 200) {
tokenVal = {
access_token: refreshResponse.knowledge?.access_token,
refresh_token: refreshResponse.knowledge?.refresh_token,
expires_in: refreshResponse.knowledge?.expires_in,
sort: 'personal',
};
} else {
// The logout will get known as a number of instances and app crashes
dispatch(logout());
tokenVal = {
access_token: null,
token_type: null,
refresh_token: null,
expires_in: null,
scope: null,
id_token: null,
sort: 'public',
};
tokenVal = await refreshPublicToken();
navigation.dispatch(StackActions.change(NAVIGATION_SCREENS.ROOT));
}
return tokenVal;
};