diff --git a/packages/app-check/src/debug.ts b/packages/app-check/src/debug.ts index 2e823d4d17d..da6cffbfcc4 100644 --- a/packages/app-check/src/debug.ts +++ b/packages/app-check/src/debug.ts @@ -17,18 +17,13 @@ import { getDebugState } from './state'; import { readOrCreateDebugTokenFromStorage } from './storage'; -import { Deferred } from '@firebase/util'; +import { Deferred, getGlobal } from '@firebase/util'; declare global { - interface Window { - /** - * When it is a string, we treat it as the debug token and give it to consumers as the app check token - * When it is `true`, we will try to read the debug token from the indexeddb, - * if it doesn't exist, create one, print it to console, and ask developers to register it in the Firebase console. - * When it is `undefined`, `false` or any unsupported value type, the SDK will operate in production mode - */ - FIREBASE_APPCHECK_DEBUG_TOKEN?: boolean | string; - } + // var must be used for global scopes + // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#type-checking-for-globalthis + // eslint-disable-next-line no-var + var FIREBASE_APPCHECK_DEBUG_TOKEN: boolean | string | undefined; } export function isDebugMode(): boolean { @@ -50,9 +45,10 @@ export async function getDebugToken(): Promise { } export function initializeDebugMode(): void { + const globals = getGlobal(); if ( - typeof self.FIREBASE_APPCHECK_DEBUG_TOKEN !== 'string' && - self.FIREBASE_APPCHECK_DEBUG_TOKEN !== true + typeof globals.FIREBASE_APPCHECK_DEBUG_TOKEN !== 'string' && + globals.FIREBASE_APPCHECK_DEBUG_TOKEN !== true ) { return; } @@ -62,8 +58,8 @@ export function initializeDebugMode(): void { const deferredToken = new Deferred(); debugState.token = deferredToken; - if (typeof self.FIREBASE_APPCHECK_DEBUG_TOKEN === 'string') { - deferredToken.resolve(self.FIREBASE_APPCHECK_DEBUG_TOKEN); + if (typeof globals.FIREBASE_APPCHECK_DEBUG_TOKEN === 'string') { + deferredToken.resolve(globals.FIREBASE_APPCHECK_DEBUG_TOKEN); } else { deferredToken.resolve(readOrCreateDebugTokenFromStorage()); } diff --git a/packages/database/src/realtime/WebSocketConnection.ts b/packages/database/src/realtime/WebSocketConnection.ts index 6038f473a7d..81c91a95093 100644 --- a/packages/database/src/realtime/WebSocketConnection.ts +++ b/packages/database/src/realtime/WebSocketConnection.ts @@ -166,9 +166,16 @@ export class WebSocketConnection implements Transport { } }; + // If using Node with admin creds, AppCheck-related checks are unnecessary. + // It will send the authorization token. if (this.nodeAdmin) { options.headers['Authorization'] = this.authToken || ''; } else { + // If using Node without admin creds (which includes all uses of the + // client-side Node SDK), it will send an AppCheck token if available. + // Any other auth credentials will eventually be sent after the connection + // is established, but aren't needed here as they don't effect the initial + // request to establish a connection. options.headers['X-Firebase-AppCheck'] = this.appCheckToken || ''; } diff --git a/packages/util/src/environment.ts b/packages/util/src/environment.ts index 92fdd4478c7..f2ad5306583 100644 --- a/packages/util/src/environment.ts +++ b/packages/util/src/environment.ts @@ -189,3 +189,20 @@ export function areCookiesEnabled(): boolean { } return true; } + +/** + * Polyfill for `globalThis` object. + * @returns the `globalThis` object for the given environment. + */ +export function getGlobal(): typeof globalThis { + if (typeof self !== 'undefined') { + return self; + } + if (typeof window !== 'undefined') { + return window; + } + if (typeof global !== 'undefined') { + return global; + } + throw new Error('Unable to locate global object.'); +}