Skip to content

Commit dcd8094

Browse files
committed
Add comprehensive environment variable and Firebase Admin debug endpoints
Created two debug endpoints to troubleshoot the Firebase Admin issue: 1. /api/debug/env-check - Shows all environment variables and their status 2. /api/debug/firebase-test - Step-by-step Firebase Admin initialization test These will help identify exactly why Firebase Admin ID token verification is failing even though the environment variables are set in Vercel.
1 parent ed095d2 commit dcd8094

File tree

2 files changed

+254
-0
lines changed

2 files changed

+254
-0
lines changed

app/api/debug/env-check/route.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
3+
/**
4+
* Debug endpoint to check what environment variables are actually available
5+
* This helps debug environment variable issues in Vercel
6+
*/
7+
export async function GET(request: NextRequest) {
8+
try {
9+
console.log('[Env Check] Environment variables debug endpoint called');
10+
11+
const envCheck = {
12+
timestamp: new Date().toISOString(),
13+
environment: {
14+
nodeEnv: process.env.NODE_ENV,
15+
vercelEnv: process.env.VERCEL_ENV,
16+
},
17+
googleCloudVars: {
18+
hasGoogleCloudKeyBase64: !!process.env.GOOGLE_CLOUD_KEY_BASE64,
19+
hasGoogleCloudKeyJson: !!process.env.GOOGLE_CLOUD_KEY_JSON,
20+
hasGoogleCloudCredentials: !!process.env.GOOGLE_CLOUD_CREDENTIALS,
21+
hasLoggingCloudKeyJson: !!process.env.LOGGING_CLOUD_KEY_JSON,
22+
googleCloudKeyJsonLength: process.env.GOOGLE_CLOUD_KEY_JSON?.length || 0,
23+
loggingCloudKeyJsonLength: process.env.LOGGING_CLOUD_KEY_JSON?.length || 0,
24+
googleCloudKeyJsonPreview: process.env.GOOGLE_CLOUD_KEY_JSON?.substring(0, 50) + '...',
25+
loggingCloudKeyJsonPreview: process.env.LOGGING_CLOUD_KEY_JSON?.substring(0, 50) + '...'
26+
},
27+
firebaseVars: {
28+
hasFirebaseProjectId: !!process.env.FIREBASE_PROJECT_ID,
29+
hasNextPublicFirebasePid: !!process.env.NEXT_PUBLIC_FIREBASE_PID,
30+
firebaseProjectId: process.env.FIREBASE_PROJECT_ID,
31+
nextPublicFirebasePid: process.env.NEXT_PUBLIC_FIREBASE_PID,
32+
hasFirebasePrivateKey: !!process.env.FIREBASE_PRIVATE_KEY,
33+
hasFirebaseClientEmail: !!process.env.FIREBASE_CLIENT_EMAIL
34+
},
35+
allEnvVarsStartingWithGoogle: Object.keys(process.env)
36+
.filter(key => key.toLowerCase().includes('google') || key.toLowerCase().includes('cloud'))
37+
.map(key => ({
38+
key,
39+
hasValue: !!process.env[key],
40+
length: process.env[key]?.length || 0
41+
})),
42+
allEnvVarsStartingWithFirebase: Object.keys(process.env)
43+
.filter(key => key.toLowerCase().includes('firebase'))
44+
.map(key => ({
45+
key,
46+
hasValue: !!process.env[key],
47+
length: process.env[key]?.length || 0
48+
}))
49+
};
50+
51+
// Try to parse the Google Cloud JSON to see if it's valid
52+
if (process.env.GOOGLE_CLOUD_KEY_JSON) {
53+
try {
54+
let jsonString = process.env.GOOGLE_CLOUD_KEY_JSON;
55+
56+
// Check if it's base64 encoded
57+
if (!jsonString.includes(' ') && !jsonString.startsWith('{')) {
58+
try {
59+
jsonString = Buffer.from(jsonString, 'base64').toString('utf-8');
60+
envCheck.googleCloudVars.isBase64Encoded = true;
61+
} catch (e) {
62+
envCheck.googleCloudVars.base64DecodeError = e.message;
63+
}
64+
}
65+
66+
const parsed = JSON.parse(jsonString);
67+
envCheck.googleCloudVars.jsonParseSuccess = true;
68+
envCheck.googleCloudVars.parsedFields = {
69+
hasProjectId: !!parsed.project_id,
70+
hasPrivateKey: !!parsed.private_key,
71+
hasClientEmail: !!parsed.client_email,
72+
projectId: parsed.project_id,
73+
clientEmail: parsed.client_email
74+
};
75+
} catch (parseError) {
76+
envCheck.googleCloudVars.jsonParseError = parseError.message;
77+
}
78+
}
79+
80+
return NextResponse.json(envCheck, {
81+
status: 200,
82+
headers: {
83+
'Cache-Control': 'no-cache, no-store, must-revalidate'
84+
}
85+
});
86+
87+
} catch (error) {
88+
console.error('[Env Check] Error:', error);
89+
90+
return NextResponse.json({
91+
error: 'Failed to check environment variables',
92+
details: error instanceof Error ? error.message : 'Unknown error',
93+
timestamp: new Date().toISOString()
94+
}, { status: 500 });
95+
}
96+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
3+
/**
4+
* Debug endpoint to test Firebase Admin initialization step by step
5+
*/
6+
export async function GET(request: NextRequest) {
7+
try {
8+
console.log('[Firebase Test] Starting Firebase Admin test...');
9+
10+
const testResults = {
11+
timestamp: new Date().toISOString(),
12+
steps: []
13+
};
14+
15+
// Step 1: Check environment variables
16+
testResults.steps.push({
17+
step: 1,
18+
name: 'Environment Variables Check',
19+
success: true,
20+
data: {
21+
hasGoogleCloudKeyJson: !!process.env.GOOGLE_CLOUD_KEY_JSON,
22+
hasLoggingCloudKeyJson: !!process.env.LOGGING_CLOUD_KEY_JSON,
23+
nodeEnv: process.env.NODE_ENV,
24+
vercelEnv: process.env.VERCEL_ENV
25+
}
26+
});
27+
28+
// Step 2: Try to parse service account JSON
29+
let serviceAccount = null;
30+
try {
31+
if (process.env.GOOGLE_CLOUD_KEY_JSON) {
32+
let jsonString = process.env.GOOGLE_CLOUD_KEY_JSON;
33+
34+
// Handle base64 encoding
35+
if (!jsonString.includes(' ') && !jsonString.startsWith('{')) {
36+
jsonString = Buffer.from(jsonString, 'base64').toString('utf-8');
37+
}
38+
39+
serviceAccount = JSON.parse(jsonString);
40+
41+
testResults.steps.push({
42+
step: 2,
43+
name: 'Service Account JSON Parse',
44+
success: true,
45+
data: {
46+
projectId: serviceAccount.project_id,
47+
clientEmail: serviceAccount.client_email,
48+
hasPrivateKey: !!serviceAccount.private_key,
49+
privateKeyLength: serviceAccount.private_key?.length || 0
50+
}
51+
});
52+
} else {
53+
throw new Error('No GOOGLE_CLOUD_KEY_JSON found');
54+
}
55+
} catch (error) {
56+
testResults.steps.push({
57+
step: 2,
58+
name: 'Service Account JSON Parse',
59+
success: false,
60+
error: error.message
61+
});
62+
63+
return NextResponse.json(testResults, { status: 200 });
64+
}
65+
66+
// Step 3: Try to initialize Firebase Admin
67+
try {
68+
const admin = await import('firebase-admin');
69+
70+
// Check if already initialized
71+
if (admin.apps.length > 0) {
72+
testResults.steps.push({
73+
step: 3,
74+
name: 'Firebase Admin Already Initialized',
75+
success: true,
76+
data: {
77+
appsCount: admin.apps.length,
78+
projectId: admin.apps[0]?.options?.projectId
79+
}
80+
});
81+
} else {
82+
// Try to initialize
83+
const app = admin.initializeApp({
84+
credential: admin.credential.cert(serviceAccount),
85+
databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL || 'https://wewrite-ccd82-default-rtdb.firebaseio.com'
86+
});
87+
88+
testResults.steps.push({
89+
step: 3,
90+
name: 'Firebase Admin Initialization',
91+
success: true,
92+
data: {
93+
projectId: app.options.projectId,
94+
databaseURL: app.options.databaseURL
95+
}
96+
});
97+
}
98+
99+
// Step 4: Try to get Auth instance
100+
const auth = admin.auth();
101+
testResults.steps.push({
102+
step: 4,
103+
name: 'Firebase Admin Auth Instance',
104+
success: true,
105+
data: {
106+
hasAuth: !!auth,
107+
authType: typeof auth
108+
}
109+
});
110+
111+
// Step 5: Try to create a test token (this will fail but shows if auth works)
112+
try {
113+
const testToken = await auth.createCustomToken('test-uid');
114+
testResults.steps.push({
115+
step: 5,
116+
name: 'Test Token Creation',
117+
success: true,
118+
data: {
119+
tokenLength: testToken.length
120+
}
121+
});
122+
} catch (tokenError) {
123+
testResults.steps.push({
124+
step: 5,
125+
name: 'Test Token Creation',
126+
success: false,
127+
error: tokenError.message,
128+
note: 'This might fail but shows if auth instance works'
129+
});
130+
}
131+
132+
} catch (error) {
133+
testResults.steps.push({
134+
step: 3,
135+
name: 'Firebase Admin Initialization',
136+
success: false,
137+
error: error.message,
138+
stack: error.stack
139+
});
140+
}
141+
142+
return NextResponse.json(testResults, {
143+
status: 200,
144+
headers: {
145+
'Cache-Control': 'no-cache, no-store, must-revalidate'
146+
}
147+
});
148+
149+
} catch (error) {
150+
console.error('[Firebase Test] Error:', error);
151+
152+
return NextResponse.json({
153+
error: 'Firebase test failed',
154+
details: error instanceof Error ? error.message : 'Unknown error',
155+
timestamp: new Date().toISOString()
156+
}, { status: 500 });
157+
}
158+
}

0 commit comments

Comments
 (0)