refactor(api): add same-origin backend proxy for auth cookies

This commit is contained in:
2026-07-22 16:18:17 +05:30
parent e077467bce
commit 5d3dac0b21
4 changed files with 23 additions and 16 deletions

View File

@@ -1,2 +1,5 @@
# Backend API base URL (no trailing slash) # Server-only backend origin. Do not expose this as a NEXT_PUBLIC variable.
NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1 BACKEND_ORIGIN=http://localhost:8000
# Browser requests stay on the Next.js origin and are rewritten server-side.
NEXT_PUBLIC_API_URL=/backend/

View File

@@ -1,7 +1,21 @@
import type { NextConfig } from 'next'; import type { NextConfig } from 'next';
const backendOrigin = process.env.BACKEND_ORIGIN?.replace(/\/+$/, '');
if (!backendOrigin) {
throw new Error('BACKEND_ORIGIN is required');
}
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
reactStrictMode: false, reactStrictMode: false,
async rewrites() {
return [
{
source: '/backend/:path*',
destination: `${backendOrigin}/:path*`,
},
];
},
}; };
export default nextConfig; export default nextConfig;

View File

@@ -14,9 +14,6 @@ export const authService = {
const response = await axiosAuth.post<AuthResponseData>( const response = await axiosAuth.post<AuthResponseData>(
API_ROUTES.AUTH.LOGIN, API_ROUTES.AUTH.LOGIN,
payload, payload,
{
withCredentials: true,
},
); );
return response.data; return response.data;
}, },
@@ -24,14 +21,11 @@ export const authService = {
const response = await axiosAuth.post<AuthResponseData>( const response = await axiosAuth.post<AuthResponseData>(
API_ROUTES.AUTH.REFRESH, API_ROUTES.AUTH.REFRESH,
{}, {},
{
withCredentials: true,
},
); );
return response.data; return response.data;
}, },
logout: async (): Promise<void> => { logout: async (): Promise<void> => {
await axiosAuth.post(API_ROUTES.AUTH.LOGOUT, {}, { withCredentials: true }); await axiosAuth.post(API_ROUTES.AUTH.LOGOUT, {});
}, },
me: async (): Promise<MeResponse> => { me: async (): Promise<MeResponse> => {
const response = await axiosClient.get<MeResponse>(API_ROUTES.AUTH.ME); const response = await axiosClient.get<MeResponse>(API_ROUTES.AUTH.ME);

View File

@@ -7,6 +7,7 @@ const BASE_URL = ENV_CONSTANT.BASE_API_URL;
const axiosClient = axios.create({ const axiosClient = axios.create({
baseURL: BASE_URL, baseURL: BASE_URL,
withCredentials: true,
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
@@ -14,6 +15,7 @@ const axiosClient = axios.create({
export const axiosAuth = axios.create({ export const axiosAuth = axios.create({
baseURL: BASE_URL, baseURL: BASE_URL,
withCredentials: true,
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
@@ -30,13 +32,7 @@ const isInvalidSessionResponse = (error: unknown) => {
const refreshAccessToken = () => { const refreshAccessToken = () => {
if (!refreshPromise) { if (!refreshPromise) {
refreshPromise = axiosAuth refreshPromise = axiosAuth
.post( .post('api/auth/refresh', {})
'api/auth/refresh',
{},
{
withCredentials: true,
},
)
.then((response) => { .then((response) => {
const accessToken = response.data?.access_token; const accessToken = response.data?.access_token;