Skip to content

Instantly share code, notes, and snippets.

@gndplayground
Last active April 27, 2023 09:50
Show Gist options
  • Save gndplayground/cb997bfbc36d9118886e0891ae08211a to your computer and use it in GitHub Desktop.
Save gndplayground/cb997bfbc36d9118886e0891ae08211a to your computer and use it in GitHub Desktop.
Axios interceptor get new token when token expired example with typescript.
import axios from 'axios';
// Example request
// axios
// .get("http://localhost:8000/get?t=1")
// .then(() => {
// console.log("ok1");
// })
// .catch(e => {
// console.log("err1");
// });
// axios
// .get("http://localhost:8000/get?t=2")
// .then(() => {
// console.log("ok2");
// })
// .catch(e => {
// console.log("err2");
// });
interface FetchTokenResponse {
token: string;
}
interface QueueItem {
resolve: (value?: string | PromiseLike<string> | undefined) => void;
reject: (reason?: any) => void;
}
let isRefreshing = false;
// Store requests that waiting for refresh token
let queue: QueueItem[] = [];
function handleQueue(err: Error | null, token = '') {
queue.forEach((prom) => {
if (err) {
prom.reject(err);
} else {
prom.resolve(token);
}
});
queue = [];
}
const refreshTokenUrl = 'http://localhost:8000/refresh';
axios.interceptors.response.use(
(response) => {
return response;
},
(error) => {
const originalRequest = error.config;
// If error from refresh token api we immediately return error
if (originalRequest.url === refreshTokenUrl) {
return Promise.reject(error);
}
if (error.response.status === 403) {
// If response status 403 no permission for the request we can force user logout
// Ex: store.dispatch(usersActions.logout());
return Promise.reject(error);
}
if (error.response.status !== 401) {
// Other error not 401 we can safely return error
return Promise.reject(error);
}
// There are no request trying to get the refresh token
if (!isRefreshing && !originalRequest._retry) {
originalRequest._retry = true;
isRefreshing = true;
// If your refresh token api require refresh token.
// You need to get current user refresh token.
// Either in local storage example like window.localStorage.getItem('refreshToken');
// Or redux example like store.getState().user.information.refreshToken.
// That depend in your setup, your code base, your method.
// The example here assume refresh token api require no refresh token
return new Promise((resolve, reject) => {
axios
.get<FetchTokenResponse>(refreshTokenUrl)
.then((res) => {
// For demo purpose, using query token. If your request require Bearer in the header
// you can check the line below
// originalRequest.headers.Authorization = 'Bearer ' + res.data.token;
// If you are using default header. Make sure set default token again
// or every next request have to call refresh token
// axios.defaults.headers.common.Authorization = res.data.token;
originalRequest.url =
originalRequest.url + '&token=' + res.data.token;
resolve(axios(originalRequest));
handleQueue(null, res.data.token);
})
.catch((err) => {
// If can't get new token when we might need force user logout
// Ex: store.dispatch(usersActions.logout());
handleQueue(err);
// Handle your logic when get token failed
reject(err);
})
.then(() => {
isRefreshing = false;
});
});
}
// There are a request trying to get the refresh token
if (isRefreshing) {
return new Promise<string>((resolve, reject) => {
queue.push({resolve, reject});
})
.then((token) => {
// For demo purpose, using query token. If your request require Bearer in the header
// you can check the line below
// originalRequest.headers.Authorization = 'Bearer ' + res.data.token;
originalRequest.url = originalRequest.url + '&token=' + token;
return axios(originalRequest);
})
.catch((err) => {
return err;
});
}
return Promise.reject(error);
},
);
// Example server response
const express = require("express");
const cors = require("cors");
const app = express();
const port = 8000;
app.use(cors());
app.get("/get", (req, res) => {
if (req.query.token !== "token") {
return res.status(401).json({ err: "no token" });
}
return res.send("Hello World!");
});
app.get("/refresh", (req, res) =>
res.json({
token: "token"
})
);
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment