How to make authenticated fetch request using Tanstack query?

I am having trouble figuring this out. Apologies, if this is something very straightforward which I am missing. How can I make an authenticated request to an API? In Expo, I can do this,
const makeAuthenticatedRequest = async () => {
const cookies = authClient.getCookie();
const headers = {
"Cookie": cookies,
};
const response = await fetch("http://localhost:8081/api/secure-endpoint", { headers });
const data = await response.json();
return data;
};
const makeAuthenticatedRequest = async () => {
const cookies = authClient.getCookie();
const headers = {
"Cookie": cookies,
};
const response = await fetch("http://localhost:8081/api/secure-endpoint", { headers });
const data = await response.json();
return data;
};
What's the equivalent in Nextjs?
1 Reply
FalconiZzare
FalconiZzare3mo ago
I'm using axios with Tanstack Query, so in my setup tanstack query is just a tool to make calls and cache responses. First, I'm making a template header for axios to include cookies with each request. You can make multiple combination of template headers as per your need. (application/json and multipart/form-data depending on your need)
export const betterAuthHeader = () => {
return {
withCredentials: true,
headers: {
"Content-Type": "application/json"
}
};
};

export const betterAuthMultipartHeader = () => {
return {
withCredentials: true,
headers: {
"Content-Type": "multipart/form-data"
}
};
};
export const betterAuthHeader = () => {
return {
withCredentials: true,
headers: {
"Content-Type": "application/json"
}
};
};

export const betterAuthMultipartHeader = () => {
return {
withCredentials: true,
headers: {
"Content-Type": "multipart/form-data"
}
};
};
Second, im defining axios requests with request URLs for my protected routes.
export const getWeeklyChartData = async () => {
const date = new Date().toISOString();

return await axios.get(`${BASE_URL}/${NUTRITION_ENDPOINT}/weeklyChart/${date}`, {
...betterAuthHeader()
});
};
export const getWeeklyChartData = async () => {
const date = new Date().toISOString();

return await axios.get(`${BASE_URL}/${NUTRITION_ENDPOINT}/weeklyChart/${date}`, {
...betterAuthHeader()
});
};
That's it for frontend/NextJs part. withCredentials: true attribute will make sure to send the cookie and other auth headers. Now you gotta parse the request on backend. I'm using ExpressJs. First I created an authMiddleware that will be included in each protected routes.
import { fromNodeHeaders } from "better-auth/node";
import { auth } from "../auth.js";

export default async function authMiddleware(req, res, next) {
try {
const session = await auth.api.getSession({
headers: fromNodeHeaders(req.headers)
});

if (!session || !session.user)
return res.status(401).json({
message: "Authentication required.",
success: false
});

req.userId = session.session.userId;

next();
} catch (err) {
console.error(err);
res.status(500).json({ message: "Server error!", success: false });
}
}
import { fromNodeHeaders } from "better-auth/node";
import { auth } from "../auth.js";

export default async function authMiddleware(req, res, next) {
try {
const session = await auth.api.getSession({
headers: fromNodeHeaders(req.headers)
});

if (!session || !session.user)
return res.status(401).json({
message: "Authentication required.",
success: false
});

req.userId = session.session.userId;

next();
} catch (err) {
console.error(err);
res.status(500).json({ message: "Server error!", success: false });
}
}
Notice I attached the userId to req if session exits. This is handy when you have to perform DB operation based on user and don't user id to be passed from frontend (security risk) Finally, include the middleware in your protected routes.
// @route GET api/nutrition/weeklyChart/:date
// @desc GET weekly nutrition chart data
// @access Private
router.get("/weeklyChart/:date", authMiddleware, nutritionController.getWeeklyNutritionChart);
// @route GET api/nutrition/weeklyChart/:date
// @desc GET weekly nutrition chart data
// @access Private
router.get("/weeklyChart/:date", authMiddleware, nutritionController.getWeeklyNutritionChart);
the authController will be executed before processing validations and forwarding the request to controller. @Ping hi... notice any security flaw in this approach?

Did you find this page helpful?