more debug

This commit is contained in:
zramsay 2025-03-11 16:35:34 -04:00
parent 20df9b5b27
commit a12079649c
5 changed files with 330 additions and 43 deletions

92
package-lock.json generated
View File

@ -14,6 +14,7 @@
"@solana/spl-token": "^0.3.8",
"@solana/web3.js": "^1.78.4",
"@supabase/supabase-js": "^2.49.1",
"@types/jsonwebtoken": "^9.0.9",
"@types/multer": "^1.4.12",
"axios": "^1.7.9",
"browser-image-compression": "^2.0.2",
@ -21,6 +22,7 @@
"file-type": "^20.0.1",
"form-data": "^4.0.1",
"formidable": "^3.5.2",
"jsonwebtoken": "^9.0.2",
"lucide-react": "^0.469.0",
"multer": "^1.4.5-lts.1",
"next": "^15.1.4",
@ -1178,6 +1180,15 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true
},
"node_modules/@types/jsonwebtoken": {
"version": "9.0.9",
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.9.tgz",
"integrity": "sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ==",
"dependencies": {
"@types/ms": "*",
"@types/node": "*"
}
},
"node_modules/@types/long": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz",
@ -1190,6 +1201,11 @@
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
"license": "MIT"
},
"node_modules/@types/ms": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
"integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="
},
"node_modules/@types/multer": {
"version": "1.4.12",
"resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.12.tgz",
@ -4877,6 +4893,46 @@
"node": "*"
}
},
"node_modules/jsonwebtoken": {
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
"dependencies": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1",
"semver": "^7.5.4"
},
"engines": {
"node": ">=12",
"npm": ">=6"
}
},
"node_modules/jsonwebtoken/node_modules/jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"dependencies": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jsonwebtoken/node_modules/jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"dependencies": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jsx-ast-utils": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
@ -4989,12 +5045,47 @@
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
"license": "MIT"
},
"node_modules/lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
},
"node_modules/lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
},
"node_modules/lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
},
"node_modules/lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
},
"node_modules/lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
},
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
"node_modules/lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
},
"node_modules/long": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
@ -6342,7 +6433,6 @@
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"devOptional": true,
"bin": {
"semver": "bin/semver.js"
},

View File

@ -15,6 +15,7 @@
"@solana/spl-token": "^0.3.8",
"@solana/web3.js": "^1.78.4",
"@supabase/supabase-js": "^2.49.1",
"@types/jsonwebtoken": "^9.0.9",
"@types/multer": "^1.4.12",
"axios": "^1.7.9",
"browser-image-compression": "^2.0.2",
@ -22,6 +23,7 @@
"file-type": "^20.0.1",
"form-data": "^4.0.1",
"formidable": "^3.5.2",
"jsonwebtoken": "^9.0.2",
"lucide-react": "^0.469.0",
"multer": "^1.4.5-lts.1",
"next": "^15.1.4",

View File

@ -89,6 +89,49 @@ const authOptions = {
}
};
// Create detailed error response with full information
function createDetailedErrorResponse(title: string, error: any, req?: Request) {
const errorObj = error instanceof Error ? {
name: error.name,
message: error.message,
stack: error.stack?.split('\n').map(line => line.trim()),
} : String(error);
const errorDetails = {
error: title,
timestamp: new Date().toISOString(),
details: errorObj,
request: req ? {
url: req.url,
method: req.method,
headers: {
host: req.headers.get('host'),
referer: req.headers.get('referer'),
'user-agent': req.headers.get('user-agent'),
}
} : undefined,
env: {
node_env: process.env.NODE_ENV,
nextauth_url: process.env.NEXTAUTH_URL,
has_secret: !!process.env.NEXTAUTH_SECRET,
has_google: !!process.env.GOOGLE_CLIENT_ID && !!process.env.GOOGLE_CLIENT_SECRET,
}
};
console.error("AUTH ERROR DETAILS:", JSON.stringify(errorDetails, null, 2));
return new Response(
JSON.stringify(errorDetails),
{
status: 500,
headers: {
"Content-Type": "application/json",
"Cache-Control": "no-store, max-age=0"
}
}
);
}
// Wrap NextAuth in a try-catch block to catch initialization errors
let handler;
try {
@ -96,27 +139,13 @@ try {
console.log("NextAuth handler initialized successfully");
} catch (error) {
console.error("CRITICAL ERROR: NextAuth initialization failed:", error);
// Create a fallback handler that logs the error and returns a 500
// Create a fallback handler that returns detailed error information
const errorHandler = {
GET: async (req: Request) => {
console.error("NextAuth GET error handler triggered for URL:", req.url);
return new Response(
JSON.stringify({
error: "Auth system initialization failed",
message: "Check server logs"
}),
{ status: 500, headers: { "Content-Type": "application/json" } }
);
return createDetailedErrorResponse("Auth system initialization failed", error, req);
},
POST: async (req: Request) => {
console.error("NextAuth POST error handler triggered for URL:", req.url);
return new Response(
JSON.stringify({
error: "Auth system initialization failed",
message: "Check server logs"
}),
{ status: 500, headers: { "Content-Type": "application/json" } }
);
return createDetailedErrorResponse("Auth system initialization failed", error, req);
}
};
handler = { handlers: errorHandler };
@ -125,24 +154,82 @@ try {
// Export handlers with additional error handling
export async function GET(req: Request) {
try {
return await handler.handlers.GET(req);
// Check for debug header
const isDebug = req.headers.get('x-debug-info') === 'true';
if (isDebug) {
console.log('DEBUG request to NextAuth endpoint:', req.url);
console.log('DEBUG Headers:',
[...req.headers.entries()].reduce((obj, [key, val]) => {
obj[key] = val;
return obj;
}, {} as Record<string, string>)
);
}
try {
// Attempt to handle the request
return await handler.handlers.GET(req);
} catch (error) {
console.error('NextAuth GET handler error:', error);
// If there's a debug header, also send the error information in the response
if (isDebug) {
return createDetailedErrorResponse("NextAuth GET operation failed", error, req);
}
// Otherwise, return a standard NextAuth error
return new Response(
JSON.stringify({
error: "Failed to handle authentication request",
message: error instanceof Error ? error.message : String(error)
}),
{ status: 500, headers: { "Content-Type": "application/json" } }
);
}
} catch (error) {
console.error("NextAuth GET error:", error);
return new Response(
JSON.stringify({ error: "Auth operation failed", details: String(error) }),
{ status: 500, headers: { "Content-Type": "application/json" } }
);
// This catches errors in our error handling
console.error('Critical error in NextAuth GET wrapper:', error);
return createDetailedErrorResponse("Critical NextAuth error", error, req);
}
}
export async function POST(req: Request) {
try {
return await handler.handlers.POST(req);
// Check for debug header
const isDebug = req.headers.get('x-debug-info') === 'true';
if (isDebug) {
console.log('DEBUG request to NextAuth POST endpoint:', req.url);
console.log('DEBUG Headers:',
[...req.headers.entries()].reduce((obj, [key, val]) => {
obj[key] = val;
return obj;
}, {} as Record<string, string>)
);
}
try {
// Attempt to handle the request
return await handler.handlers.POST(req);
} catch (error) {
console.error('NextAuth POST handler error:', error);
// If there's a debug header, also send the error information in the response
if (isDebug) {
return createDetailedErrorResponse("NextAuth POST operation failed", error, req);
}
// Otherwise, return a standard NextAuth error
return new Response(
JSON.stringify({
error: "Failed to handle authentication request",
message: error instanceof Error ? error.message : String(error)
}),
{ status: 500, headers: { "Content-Type": "application/json" } }
);
}
} catch (error) {
console.error("NextAuth POST error:", error);
return new Response(
JSON.stringify({ error: "Auth operation failed", details: String(error) }),
{ status: 500, headers: { "Content-Type": "application/json" } }
);
// This catches errors in our error handling
console.error('Critical error in NextAuth POST wrapper:', error);
return createDetailedErrorResponse("Critical NextAuth error", error, req);
}
}

View File

@ -0,0 +1,62 @@
import { NextRequest, NextResponse } from 'next/server';
import * as jwt from 'jsonwebtoken';
export async function GET(request: NextRequest) {
try {
// Test if we can sign and verify JWTs - this is a common issue with NextAuth
const testObj = { test: 'data', timestamp: Date.now() };
let jwtResults = {};
if (process.env.NEXTAUTH_SECRET) {
try {
// Try to sign a token with the secret
const token = jwt.sign(testObj, process.env.NEXTAUTH_SECRET, { expiresIn: '5m' });
// Try to verify the token
const decoded = jwt.verify(token, process.env.NEXTAUTH_SECRET);
jwtResults = {
signed: true,
verified: true,
token_excerpt: `${token.substring(0, 20)}...`,
decoded
};
} catch (jwtError) {
jwtResults = {
error: String(jwtError),
signed: false,
verified: false
};
}
} else {
jwtResults = {
error: 'NEXTAUTH_SECRET is not defined',
signed: false,
verified: false
};
}
// Test cookie functionality
const cookieTest = {
can_set_cookies: true,
settings: {
secure: process.env.NODE_ENV === 'production',
domain: new URL(process.env.NEXTAUTH_URL || `https://${request.headers.get('host')}`).hostname,
}
};
return NextResponse.json({
success: true,
jwt_test: jwtResults,
cookie_test: cookieTest,
timestamp: new Date().toISOString(),
});
} catch (error) {
console.error('JWT test error:', error);
return NextResponse.json({
success: false,
error: String(error),
stack: error instanceof Error ? error.stack : undefined
}, { status: 500 });
}
};

View File

@ -10,31 +10,55 @@ export default function DebugPage() {
const [authData, setAuthData] = useState<any>(null);
const [serverEnv, setServerEnv] = useState<any>(null);
const [authCheck, setAuthCheck] = useState<any>(null);
const [jwtTest, setJwtTest] = useState<any>(null);
const [authError, setAuthError] = useState<string | null>(null);
useEffect(() => {
const checkAuth = async () => {
try {
const res = await fetch('/api/auth/session');
// Let's make a specific fetch with all details for debugging
const res = await fetch('/api/auth/session', {
method: 'GET',
credentials: 'include',
headers: {
'Accept': 'application/json',
'X-Debug-Info': 'true'
}
});
// Get the response text first for debugging
const responseText = await res.text();
console.log('Auth session raw response:', responseText);
if (res.ok) {
const data = await res.json();
setAuthData(data);
} else {
setAuthError(`Session API error: ${res.status} ${res.statusText}`);
// Try to get error details from body
try {
const errorData = await res.json();
console.error('Auth session error details:', errorData);
if (errorData.error) {
setAuthError(prev => `${prev} - ${errorData.error}`);
}
const data = JSON.parse(responseText);
setAuthData(data);
} catch (e) {
// Couldn't parse body
setAuthError(`Session API returned invalid JSON: ${responseText.substring(0, 100)}`);
}
} else {
// Create detailed error information
let errorInfo = `Session API error: ${res.status} ${res.statusText}`;
// Add response body for debugging
if (responseText) {
try {
const errorData = JSON.parse(responseText);
console.error('Auth session error details:', errorData);
setAuthError(`${errorInfo}\n\nDetails: ${JSON.stringify(errorData, null, 2)}`);
} catch (e) {
// Not JSON, use raw text
errorInfo += `\n\nResponse: ${responseText.substring(0, 500)}`;
setAuthError(errorInfo);
}
} else {
setAuthError(errorInfo + " (No response body)");
}
}
} catch (error) {
console.error('Error fetching auth session', error);
setAuthError(String(error));
setAuthError(`Exception: ${String(error)}`);
}
};
@ -66,9 +90,24 @@ export default function DebugPage() {
}
};
const testJwtFunctionality = async () => {
try {
const res = await fetch('/api/debug/test-jwt');
if (res.ok) {
const data = await res.json();
setJwtTest(data);
} else {
console.error('Failed to test JWT functionality:', res.statusText);
}
} catch (error) {
console.error('Error testing JWT functionality:', error);
}
};
checkAuth();
checkServerEnv();
checkAuthConfig();
testJwtFunctionality();
}, []);
// Environment variables check (public variables only)
@ -122,6 +161,13 @@ export default function DebugPage() {
</pre>
</div>
<div className="bg-gray-700 p-4 rounded-lg">
<h2 className="text-xl font-bold text-emerald-300 mb-2">JWT Functionality Test</h2>
<pre className="bg-gray-900 p-4 rounded mt-2 overflow-auto max-h-60">
{jwtTest ? JSON.stringify(jwtTest, null, 2) : "Testing JWT functionality..."}
</pre>
</div>
<div className="bg-gray-700 p-4 rounded-lg">
<h2 className="text-xl font-bold text-emerald-300 mb-2">Client Environment Variables</h2>
<pre className="bg-gray-900 p-4 rounded mt-2 overflow-auto max-h-60">