Firebase可调用函数调用时持续返回401未认证错误,请求排查方向
Firebase可调用函数调用时持续返回401未认证错误,请求排查方向
我是个编程新手,11月底才开始用AI帮自己做一个React Web应用,现在正尝试部署到生产环境。但调用Firebase可调用函数时一直碰到401未认证错误,折腾好久了,想问问大家有没有新的排查方向😭
错误信息
Failed to load resource: the server responded with a status of 401 () LGChat.js:78 Full error object: FirebaseError: The function must be called while authenticated.
问题现状
明明我已经完全登录了,Firebase Storage能正常拉取当前账号关联的文档,说明认证功能本身没坏——我甚至删除重建过账号,确认auth流程没问题。而且根据我对可调用函数的理解,Firebase会自动处理token的生成和传递,我代码里没做过影响token的操作,但每次调用函数时,Firebase自己生成的token发过去后还是被拒绝了,实在想不通token会有问题。
已完成的排查步骤
LLM们大多建议检查环境配置,我把它们提到的每一项都核对过了,也确认自己完全登录了Google Cloud SDK。具体做过的排查包括:
- 仔细检查了所有可能的环境配置问题
- 确认已登录Google Cloud
- 对照可调用函数官方文档确认配置正确
- 核对过gcloud密钥等信息,确保无误
- 确认其他Firebase服务(比如Storage)能正常工作
- 给所有用户都设置了函数调用者权限
- 每次重新部署前都会清缓存
相关代码片段
错误是从我的functions/index.js和LGChat.js文件里抛出来的,下面是相关代码:
LGChat.js 中的函数调用代码
const processDocument = async () => { if (!selectedFile || isProcessing || isProcessed || !currentUser) return; setIsProcessing(true); setError(null); setProcessingStatus('Starting processing...'); try { // Use the already initialized functions instance from above const processPdfDocument = httpsCallable(functions, 'processPdfDocument', { timeout: 540000 }); console.log('Processing document with auth:', { uid: currentUser?.uid, email: currentUser?.email }); console.log('Document details being sent:', { fileId: selectedFile.id, fileName: selectedFile.name, fileUrl: selectedFile.url, userId: currentUser.uid }); setProcessingStatus('Processing PDF...'); console.log('Processing PDF...'); const result = await processPdfDocument({ fileId: selectedFile.id, fileName: selectedFile.name, fileUrl: selectedFile.url, userId: currentUser.uid }); console.log('Processing PDF result:', result); if (result.data?.success) { setIsProcessed(true); setProcessingStatus( `Successfully processed ${result.data.pagesProcessed} pages` ); } else { throw new Error( 'Processing failed: ' + (result.data?.error || 'Unknown error') ); } } catch (error) { console.error('Error processing document:', error); setError(error.message || 'Failed to process document.'); setIsProcessed(false); setProcessingStatus('Processing failed'); } };
functions/index.js 中的可调用函数代码
// Process PDF exports.processPdfDocument = onCall( { memory: "2GiB", timeoutSeconds: 540, cors: true, enforceAppCheck: false, secrets: [ "OPENAI_API_KEY", "PINECONE_API_KEY", "PINECONE_INDEX_NAME", "PINECONE_HOST" ] }, async (request, context) => { // Log the full context and request for debugging console.log("[processPdfDocument] Request data:", { auth: request.auth, rawRequest: request.rawRequest, data: request.data }); console.log("[processPdfDocument] Context:", { auth: context.auth, rawRequest: context.rawRequest }); // Check auth if (!request.auth) { console.error("[processPdfDocument] No auth context"); throw new HttpsError( "unauthenticated", "The function must be called while authenticated." ); } // Verify UID if (!request.auth.uid) { console.error("[processPdfDocument] No UID in auth context"); throw new HttpsError( "unauthenticated", "Invalid authentication. Please sign in again." ); } try { // Verify the token const decodedToken = await admin.auth().verifyIdToken(context.auth.token); console.log("[processPdfDocument] Token verified:", decodedToken.uid); console.log("[processPdfDocument] Auth context:", { hasAuth: Boolean(context.auth), uid: context.auth ? context.auth.uid : null, token: context.auth ? Boolean(context.auth.token) : false, app: Boolean(context.app) }); if (!request.auth || !request.auth.uid) { console.error("[processPdfDocument] Authentication error: No valid auth context"); throw new HttpsError( "unauthenticated", "The function must be called while authenticated." ); } try { console.log("[processPdfDocument] Request data:", { ...request.data, auth: {uid: context.auth.uid} }); const {fileId, fileName, path} = request.data; const uid = context.auth.uid; // Validate parameters with detailed logging const missingParams = []; if (!fileId) missingParams.push("fileId"); if (!fileName) missingParams.push("fileName"); if (!path) missingParams.push("path"); if (missingParams.length > 0) { const errorMsg = `Missing required parameters: ${missingParams.join(", ")}`; console.error("[processPdfDocument] Parameter validation failed:", { received: {fileId, fileName, path}, missing: missingParams }); throw new HttpsError("invalid-argument", errorMsg); } // Validate config with error handling let config; try { config = getConfig(); console.log("[processPdfDocument] Configuration validated successfully"); } catch (configError) { console.error("[processPdfDocument] Configuration error:", configError); throw new HttpsError( "failed-precondition", `Configuration error: ${configError.message}` ); } // Initialize storage and get file const storage = getStorage(); const bucket = storage.bucket(); const tempFilePath = `/tmp/${fileId}-${Date.now()}.pdf`; // Download file with detailed error handling try { console.log("[processPdfDocument] Attempting to download file:", {path, tempFilePath}); await bucket.file(path).download({destination: tempFilePath}); console.log("[processPdfDocument] File downloaded successfully"); } catch (downloadError) { console.error("[processPdfDocument] Download error:", { error: downloadError, path, tempFilePath }); throw new HttpsError( "internal", `Failed to download file: ${downloadError.message}` ); } // Process PDF with error handling let pdfContent; try { const dataBuffer = await fs.readFile(tempFilePath); console.log("[processPdfDocument] File read successfully, size:", dataBuffer.length); pdfContent = await pdf(dataBuffer, { pageNumbers: true, normalizeWhitespace: true, disableCombineTextItems: false }); console.log("[processPdfDocument] PDF parsed successfully, pages:", pdfContent.numpages); } catch (pdfError) { console.error("[processPdfDocument] PDF processing error:", pdfError); throw new HttpsError( "internal", `Failed to process PDF: ${pdfError.message}` ); } // Create text chunks const splitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000, chunkOverlap: 200 }); let allDocs = []; try { const docs = await splitter.createDocuments( [pdfContent.text], [{ pageNumber: 1, fileId, fileName, userId: uid }] ); allDocs = docs; console.log("[processPdfDocument] Created chunks:", allDocs.length); } catch (splitError) { console.error("[processPdfDocument] Text splitting error:", splitError); throw new HttpsError( "internal", `Failed to split text: ${splitError.message}` ); } } catch (innerError) { throw innerError; } } catch (outerError) { throw outerError; } } );
我实在没辙了,有没有大佬能给指个新方向?因为是新手,麻烦尽量讲得直白些,我可能听不懂太专业的术语😭 如果需要我提供更多信息,也请随时说!
备注:内容来源于stack exchange,提问作者user29219329
相关产品推荐
相关产品推荐

