ugh
This commit is contained in:
@@ -11,9 +11,13 @@ export async function GET(req: NextRequest) {
|
||||
// If not in headers, check cookies
|
||||
if (!token) {
|
||||
token = req.cookies.get('Authorization')?.value;
|
||||
console.log('Auth check: Token from cookies');
|
||||
console.log('Auth check: Token from cookies:', token ? `${token.substring(0, 10)}...` : 'none');
|
||||
|
||||
// Debug: List all cookies
|
||||
const cookiesList = req.cookies.getAll();
|
||||
console.log('Auth check: All cookies:', JSON.stringify(cookiesList.map(c => c.name)));
|
||||
} else {
|
||||
console.log('Auth check: Token from headers');
|
||||
console.log('Auth check: Token from headers:', token.substring(0, 10) + '...');
|
||||
}
|
||||
|
||||
if (!token) {
|
||||
|
||||
59
app/api/auth/set-cookie/route.ts
Normal file
59
app/api/auth/set-cookie/route.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
// Force dynamic execution to ensure cookies are set at runtime
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
// Parse the request body to get the auth token
|
||||
const body = await req.json();
|
||||
const { token } = body;
|
||||
|
||||
if (!token) {
|
||||
console.error('Set-cookie API: No token provided');
|
||||
return NextResponse.json(
|
||||
{ error: 'No token provided' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Create a response object
|
||||
const response = NextResponse.json(
|
||||
{ success: true },
|
||||
{ status: 200 }
|
||||
);
|
||||
|
||||
// Set the token in an HTTP-only cookie that will be sent with requests
|
||||
// The secure flag is conditionally set based on the environment
|
||||
const isLocalhost = req.headers.get('host')?.includes('localhost') ||
|
||||
req.headers.get('host')?.includes('127.0.0.1');
|
||||
|
||||
const cookieOptions = {
|
||||
// HttpOnly for security - prevents JavaScript access
|
||||
httpOnly: true,
|
||||
// Valid for 7 days (same as the JWT)
|
||||
maxAge: 7 * 24 * 60 * 60,
|
||||
// Only send in requests to our domain
|
||||
path: '/',
|
||||
// Strict same-site policy to prevent CSRF
|
||||
sameSite: 'strict' as const,
|
||||
// Secure only in production environments
|
||||
secure: !isLocalhost
|
||||
};
|
||||
|
||||
// Set the cookie with the options
|
||||
response.cookies.set('Authorization', token, cookieOptions);
|
||||
|
||||
console.log('Set-cookie API: Cookie set successfully');
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('Set-cookie API error:', error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: 'Failed to set cookie',
|
||||
details: error instanceof Error ? error.message : String(error)
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v2.5
|
||||
container_name: traefik
|
||||
command:
|
||||
- "--api.insecure=true"
|
||||
- "--log.level=DEBUG"
|
||||
- "--accesslog"
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.network=web"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--entrypoints.websecure.forwardedHeaders.trustedIPs=212.113.116.6,194.26.229.41,138.124.13.13,77.73.131.156" # Trust IPs for websecure
|
||||
- "--entrypoints.web.forwardedHeaders.trustedIPs=212.113.116.6,194.26.229.41,138.124.13.13,77.73.131.156" # Trust IPs for web
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- "/var/run/docker.sock:/var/run/docker.sock"
|
||||
networks:
|
||||
- web
|
||||
|
||||
nextjs-app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: nextjs-app-container
|
||||
expose:
|
||||
- "3000"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.nextjs-app.rule=Host(`dash.embermarket.app`) || Host(`77.73.131.156`) || PathPrefix(`/`)"
|
||||
- "traefik.http.services.nextjs-app.loadbalancer.server.port=3000"
|
||||
- "traefik.http.routers.nextjs-app-https.rule=Host(`dash.embermarket.app`) || Host(`77.73.131.156`) || PathPrefix(`/`)"
|
||||
- "traefik.http.middlewares.redirect-to-http.redirectscheme=http"
|
||||
- "traefik.http.routers.nextjs-app-https.middlewares=redirect-to-http"
|
||||
|
||||
networks:
|
||||
- web
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- NEXT_PUBLIC_API_URL=https://internal-api.inboxi.ng/api
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
web:
|
||||
external: true
|
||||
@@ -27,24 +27,16 @@ export async function fetchClient<T>(
|
||||
): Promise<T> {
|
||||
const { method = 'GET', body, headers = {}, ...rest } = options;
|
||||
|
||||
// Get the base API URL from environment or fallback
|
||||
const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
|
||||
|
||||
// Ensure the endpoint starts with a slash
|
||||
// Always use the Next.js API proxy by creating a path starting with /api/
|
||||
// This ensures requests go through Next.js rewrites
|
||||
const normalizedEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
|
||||
|
||||
// For the specific case of internal-api.inboxi.ng - remove duplicate /api
|
||||
// Construct the URL to always use the Next.js API routes
|
||||
let url;
|
||||
if (apiUrl.includes('internal-api.inboxi.ng')) {
|
||||
// Special case for internal-api.inboxi.ng
|
||||
if (normalizedEndpoint.startsWith('/api/')) {
|
||||
url = `${apiUrl}${normalizedEndpoint.substring(4)}`; // Remove the /api part
|
||||
} else {
|
||||
url = `${apiUrl}${normalizedEndpoint}`;
|
||||
}
|
||||
if (normalizedEndpoint.startsWith('/api/')) {
|
||||
url = normalizedEndpoint; // Already has /api/ prefix
|
||||
} else {
|
||||
// Normal case for other environments
|
||||
url = `${apiUrl}${normalizedEndpoint}`;
|
||||
url = `/api${normalizedEndpoint}`; // Add /api/ prefix
|
||||
}
|
||||
|
||||
// Get auth token from cookies
|
||||
|
||||
@@ -14,15 +14,17 @@ export async function clientFetch(url: string, options: RequestInit = {}): Promi
|
||||
...options.headers,
|
||||
};
|
||||
|
||||
// Ensure the url doesn't start with a slash if it's going to be appended to a URL that ends with one
|
||||
const cleanUrl = url.startsWith('/') ? url.substring(1) : url;
|
||||
const baseUrl = process.env.NEXT_PUBLIC_API_URL || '/api';
|
||||
// Always use the Next.js API proxy for consistent routing
|
||||
// Format the URL to ensure it has the /api prefix
|
||||
let fullUrl;
|
||||
if (url.startsWith('/api/')) {
|
||||
fullUrl = url; // Already has /api/ prefix
|
||||
} else {
|
||||
// Add /api prefix if not already present
|
||||
const cleanUrl = url.startsWith('/') ? url : `/${url}`;
|
||||
fullUrl = `/api${cleanUrl}`;
|
||||
}
|
||||
|
||||
// Ensure there's only one slash between the base URL and endpoint
|
||||
const fullUrl = baseUrl.endsWith('/')
|
||||
? `${baseUrl}${cleanUrl}`
|
||||
: `${baseUrl}/${cleanUrl}`;
|
||||
|
||||
const res = await fetch(fullUrl, {
|
||||
...options,
|
||||
headers,
|
||||
|
||||
@@ -91,7 +91,8 @@ export const updateProductStock = async (
|
||||
authToken: string
|
||||
) => {
|
||||
try {
|
||||
const url = `${process.env.NEXT_PUBLIC_API_URL}/stock/${productId}`;
|
||||
// Use Next.js API proxy to ensure request goes through rewrites
|
||||
const url = `/api/stock/${productId}`;
|
||||
return await fetchData(url, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
|
||||
@@ -29,10 +29,18 @@ export const apiRequest = async <T = any>(endpoint: string, method: string = "GE
|
||||
options.body = JSON.stringify(body);
|
||||
}
|
||||
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||
if (!API_URL) throw new Error("NEXT_PUBLIC_API_URL is not set in environment variables");
|
||||
// Always use the Next.js API proxy to ensure all requests go through rewrites
|
||||
// Format the endpoint to ensure it has the /api prefix
|
||||
let url;
|
||||
if (endpoint.startsWith('/api/')) {
|
||||
url = endpoint; // Already has /api/ prefix
|
||||
} else {
|
||||
// Add /api prefix and ensure no duplicate slashes
|
||||
const cleanEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
|
||||
url = `/api${cleanEndpoint}`;
|
||||
}
|
||||
|
||||
const res = await fetchData(`${API_URL}${endpoint}`, options);
|
||||
const res = await fetchData(url, options);
|
||||
|
||||
if (!res) {
|
||||
const errorResponse = await res.json().catch(() => null);
|
||||
|
||||
@@ -2,15 +2,29 @@ import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
|
||||
export async function middleware(req: NextRequest) {
|
||||
// Check for auth token in cookies
|
||||
const token = req.cookies.get("Authorization")?.value;
|
||||
|
||||
|
||||
// Debug info about all cookies
|
||||
const allCookies = req.cookies.getAll();
|
||||
console.log("Middleware: All cookies:", allCookies.map(c => c.name).join(', '));
|
||||
|
||||
if (!token) {
|
||||
console.log("Middleware: No token found, redirecting to login...");
|
||||
return NextResponse.redirect(new URL("/auth/login", req.url));
|
||||
// Try to get from Authorization header as fallback
|
||||
const authHeader = req.headers.get('Authorization');
|
||||
|
||||
if (authHeader?.startsWith('Bearer ')) {
|
||||
console.log("Middleware: Token found in Authorization header");
|
||||
// Continue with validation using header auth
|
||||
// The authCheckUrl will handle extracting the token from header
|
||||
} else {
|
||||
console.log("Middleware: No token found in cookies or headers, redirecting to login...");
|
||||
return NextResponse.redirect(new URL("/auth/login", req.url));
|
||||
}
|
||||
} else {
|
||||
console.log("Middleware: Token found in cookies, validating...");
|
||||
}
|
||||
|
||||
console.log("Middleware: Token found, validating...");
|
||||
|
||||
try {
|
||||
// Get the origin but handle localhost differently to avoid SSL issues
|
||||
const origin = req.nextUrl.origin;
|
||||
@@ -24,13 +38,17 @@ export async function middleware(req: NextRequest) {
|
||||
|
||||
console.log(`Using internal auth check URL: ${authCheckUrl}`);
|
||||
|
||||
// Clone headers to avoid modifying the original request
|
||||
const headers = new Headers(req.headers);
|
||||
|
||||
// If token is in cookie, ensure it's also in Authorization header
|
||||
if (token && !headers.has('Authorization')) {
|
||||
headers.set('Authorization', `Bearer ${token}`);
|
||||
}
|
||||
|
||||
const res = await fetch(authCheckUrl, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
// Explicitly pass the token in headers as well
|
||||
"Authorization": `Bearer ${token}`
|
||||
},
|
||||
headers,
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user