How to update session's refresh and access token manually in server action file such as axio setup?
Unanswered
rand posted this in #help-forum
randOP
Hello, folks, Im looking for a solution to implement token rotation while i call axios api call.
Here is my axios code but i dont think
How to update the session data outside of authJS?
Thank you!
Here is my axios code but i dont think
session.accessToken = responseOfTokenRefreshAPI.access works.How to update the session data outside of authJS?
Thank you!
"use server";
import { auth } from "@/auth";
import axios from "axios";
import { signOut } from "next-auth/react";
const api = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_BASE_URL,
});
let isRefreshing = false; // Track if a token refresh is in progress
let refreshSubscribers: ((token: string) => void)[] = []; // Queue requests while refreshing
// Helper to subscribe to the token refresh
const subscribeTokenRefresh = (cb: (newToken: string) => void) => {
refreshSubscribers.push(cb);
};
// Notify all subscribers with the new token
const onRefreshed = (newToken: string) => {
refreshSubscribers.forEach((cb) => cb(newToken));
refreshSubscribers = [];
};
// Request interceptor: Attach the access token
api.interceptors.request.use(async (config) => {
const session = await auth();
if (session?.accessToken) {
config.headers.Authorization = `Bearer ${session.accessToken}`;
}
return config;
});
// Response interceptor: Handle token expiration and refresh logic
api.interceptors.response.use(
(response) => response, // Return response if no error
async (error) => {
const originalRequest = error.config;
// Handle 401 errors (Unauthorized)
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
// Prevent multiple refresh requests at the same time
if (!isRefreshing) {
isRefreshing = true;
try {
// Refresh the token
const session = await auth();
if (!session?.refreshToken) {
throw new Error("No refresh token available");
}
console.log("REFRESH TOKEN", session.refreshToken)
const refreshResponse = await axios.post(
`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/auth/refresh/`,
{
refresh: session.refreshToken,
}
);
console.log("REFRESH RESPONSE:", refreshResponse.data);
const { access, refresh } = refreshResponse.data; // Extract the new access token
// Update the session with the new access token
session.accessToken = access;
session.refreshToken = refresh;
// Notify all queued requests with the new token
onRefreshed(access);
isRefreshing = false;
// Retry the original request with the new access token
return api(originalRequest);
} catch (refreshError) {
isRefreshing = false;
console.error("Token refresh failed", refreshError);
// If refresh fails, sign out the user
signOut({ callbackUrl: "/login" });
return Promise.reject(refreshError);
}
}
// Queue the failed request while refreshing
return new Promise((resolve) => {
subscribeTokenRefresh((newToken: string) => {
originalRequest.headers.Authorization = `Bearer ${newToken}`;
resolve(api(originalRequest)); // Retry with the new token
});
});
}
return Promise.reject(error); // Return other errors as-is
}
);
export default api;