From 4694fd4147e39b5a9f1ca972d4a703e41f7ecac2 Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Wed, 1 Feb 2023 12:11:33 -0500 Subject: [PATCH 1/3] quick patch to re-create the context.auth using emulator supplied headers --- src/common/providers/https.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/common/providers/https.ts b/src/common/providers/https.ts index cfa0aadec..c72d2dafd 100644 --- a/src/common/providers/https.ts +++ b/src/common/providers/https.ts @@ -36,6 +36,9 @@ import { TaskContext } from "./tasks"; const JWT_REGEX = /^[a-zA-Z0-9\-_=]+?\.[a-zA-Z0-9\-_=]+?\.([a-zA-Z0-9\-_=]+)?$/; +const CALLABLE_AUTH_HEADER = "x-callable-context-auth"; +const ORIGINAL_AUTH_HEADER = "x-original-auth"; + /** An express request with the wire format representation of the request body. */ export interface Request extends express.Request { /** The wire format representation of the request body. */ @@ -661,6 +664,29 @@ function wrapOnCallHandler( } const context: CallableContext = { rawRequest: req }; + + // This code is needed to fix v1 callable functions in the emulator with a monorepo setup. + // The original monkey-patched code lived in the functionsEmulatorRuntime + // (link: https://github.com/firebase/firebase-tools/blob/accea7abda3cc9fa6bb91368e4895faf95281c60/src/emulator/functionsEmulatorRuntime.ts#L480) + // and was not compatible with how monorepos separate out packages (see https://github.com/firebase/firebase-tools/issues/5210). + if (process.env.FUNCTIONS_EMULATOR && handler.length === 2) { + const authContext = context.rawRequest.header(CALLABLE_AUTH_HEADER); + if (authContext) { + logger.debug("Callable functions auth override", { + key: CALLABLE_AUTH_HEADER, + value: authContext, + }); + context.auth = JSON.parse(decodeURIComponent(authContext)); + delete context.rawRequest.headers[CALLABLE_AUTH_HEADER]; + } + + const originalAuth = context.rawRequest.header(ORIGINAL_AUTH_HEADER); + if (originalAuth) { + context.rawRequest.headers["authorization"] = originalAuth; + delete context.rawRequest.headers[ORIGINAL_AUTH_HEADER]; + } + } + const tokenStatus = await checkTokens(req, context); if (tokenStatus.auth === "INVALID") { throw new HttpsError("unauthenticated", "Unauthenticated"); From 12e2f83777860e90f2e94b9fc2985b061114b6f5 Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Wed, 1 Feb 2023 12:16:39 -0500 Subject: [PATCH 2/3] add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31025713e..5ba90892d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1 +1,2 @@ - Fixes an emulator issue where snapshot.ref could not point to multiple databases (#1339). +- Fixes emulated v1 callable functions that use a monorepo setup (#1345). From e73e4699815239388800a85cf7dc17fb86793cd0 Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Wed, 1 Feb 2023 16:18:17 -0500 Subject: [PATCH 3/3] Add TODO and use isDebugFeatureEnabled function --- src/common/providers/https.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/common/providers/https.ts b/src/common/providers/https.ts index c72d2dafd..3f59bfe39 100644 --- a/src/common/providers/https.ts +++ b/src/common/providers/https.ts @@ -665,11 +665,14 @@ function wrapOnCallHandler( const context: CallableContext = { rawRequest: req }; - // This code is needed to fix v1 callable functions in the emulator with a monorepo setup. + // TODO(colerogers): yank this when we release a breaking change of the CLI that removes + // our monkey-patching code referenced below and increases the minimum supported SDK version. + // + // Note: This code is needed to fix v1 callable functions in the emulator with a monorepo setup. // The original monkey-patched code lived in the functionsEmulatorRuntime // (link: https://github.com/firebase/firebase-tools/blob/accea7abda3cc9fa6bb91368e4895faf95281c60/src/emulator/functionsEmulatorRuntime.ts#L480) // and was not compatible with how monorepos separate out packages (see https://github.com/firebase/firebase-tools/issues/5210). - if (process.env.FUNCTIONS_EMULATOR && handler.length === 2) { + if (isDebugFeatureEnabled("skipTokenVerification") && handler.length === 2) { const authContext = context.rawRequest.header(CALLABLE_AUTH_HEADER); if (authContext) { logger.debug("Callable functions auth override", {