I am looking for a generic way to replay a fetch if I get a 401 response.
My application is a SPA using OIDC. Our frontend developers utilise fetch, and a ServieWorker injects the access_token into the AJAX request before sending the request to the API(s). There are times when a fetch occurs but access_token is expired. When that happens, I want to use the refresh_token to get a new access_token and then replay the fetch, returning the replayed fetch in the Promise. Ideally, this would be something the frontend developers would not even know is happening.
Meaning that a UI developer will code something like what's below (remember, the access_token is injected via ServiceWorker):
fetch("https://backend.api/user/get/1")
.then(resp =>
{
console.log("user information is XYZ. Raw response:", resp);
})
When really what's happening in the background is:
[Initial request] > [Expired token response] > [Request new token] > [Initial request replayed]
I've experimented with overriding the fetch method with what's below, but I can't figure out a generic way to recreate/clone the original fetch:
window.fetch = new Proxy(window.fetch, {
apply(fetch, that, args) {
// Forward function call to the original fetch
const result = fetch.apply(that, args);
// Do whatever you want with the resulting Promise
result.then(resp =>
{
if(resp.status == 400 || resp.status == 401)
{
let rt = getRefreshToken();
return fetch("https://idaas.provider/get/new/token", {
"method": "POST",
"body": new URLSearchParams({
grant_type: "refresh_token",
refresh_token: rt,
client_id: client_id_str
})
});
}
}).then(resp =>
{
let new_token = resp.new_token;
send_new_token_to_service_worker(new_token);
return new_token
}).then(tok =>
{
// How do I replay the original request?
})
return result;
}
});
The goal is to simplify what the UI developers need to handle. I want them focused on UX and have this sort of error handling done in the background.
Note: If necessary, I would be open to not using fetch and instead utilising a wrapper method. Obviously, because of the code already written surrounding fetch, the new method would need to accept the same arguments and produce the same return.