Skip to content

Instantly share code, notes, and snippets.

@SirojbekMaqsudov
Last active April 6, 2024 21:49
Show Gist options
  • Save SirojbekMaqsudov/0c6a1e690e9e52c5fd54376bd5ced235 to your computer and use it in GitHub Desktop.
Save SirojbekMaqsudov/0c6a1e690e9e52c5fd54376bd5ced235 to your computer and use it in GitHub Desktop.
next-auth token refresh rotation and axios interceptor
import axios from "axios";
import {getCsrfToken, getSession, signOut} from "next-auth/react";
const refreshToken = async (token) => {
const response = await fetch(`${process.env.API_URL}/auth/refresh`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
const res = await response.json();
if (res.code && res.code === 401) {
await signOut()
return;
}
await updateSession(res.data)
const reloadSession = () => {
const event = new Event("visibilitychange");
document.dispatchEvent(event);
};
if (document) reloadSession()
return res.data;
};
const updateSession = async (data) => {
const session = await getSession();
const csrfToken = await getCsrfToken();
const updatedSessionData = { ...session, ...data};
await fetch(`${process.env.NEXTAUTH_URL}/api/auth/session`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
csrfToken: csrfToken,
data: {
...updatedSessionData
}
})
});
};
let isRefreshing = false;
let refreshAndRetryQueue = []
const Api = () => {
const instance = axios.create({
baseURL: process.env.API_URL
})
instance.interceptors.request.use(async (request) => {
const session = await getSession();
if (session && session.user) {
request.headers.Authorization = `Bearer ${session.token}`;
}
return request;
});
instance.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
const session = await getSession();
if (error?.response?.status === 401 && session && session.user) {
if (!isRefreshing) {
isRefreshing = true
try {
const data = await refreshToken(session.refresh_token);
originalRequest.headers.Authorization = `Bearer ${data.token}`;
refreshAndRetryQueue.forEach(({ config, resolve, reject }) => {
instance.request(config)
.then(response => resolve(response))
.catch(err => reject(err))
})
refreshAndRetryQueue.length = 0
return axios(originalRequest);
}catch (e) {
console.log(e)
}finally {
isRefreshing = false
}
}
return new Promise((resolve, reject) => {
refreshAndRetryQueue.push({config: originalRequest, resolve, reject})
})
}
return Promise.reject(error);
}
);
return instance
}
export default Api()
@SirojbekMaqsudov
Copy link
Author

don't forget to ⭐ it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment