angular / angularfire

Angular + Firebase = ❤️
https://firebaseopensource.com/projects/angular/angularfire2
MIT License
7.64k stars 2.2k forks source link

Using with Angular 17 SSR -> document is not defined on initializeAppCheck #3488

Open jjgriff93 opened 6 months ago

jjgriff93 commented 6 months ago

Version info

Angular: 17.0.8

Firebase: 10.7.1

AngularFire: 17.0.0

Other (e.g. Ionic/Cordova, Node, browser, operating system): Node 18, Ionic 7, MacOS

How to reproduce these conditions

Steps to set up and reproduce

  1. New Angular 17 project
  2. ng add @angular/fire@17
  3. ng add @angular/ssr
  4. Set up App Check as per https://github.com/angular/angularfire/blob/master/docs/app-check.md
  5. ng build

Debug output

⠇ Building...
ReferenceError: document is not defined
    at makeDiv (/app/.angular/prerender-root/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1119:26)
    at initializeV3 (/app/.angular/prerender-root/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1064:19)
    at _ReCaptchaV3Provider.initialize (/app/.angular/prerender-root/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1255:9)
    at _activate (/app/.angular/prerender-root/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1543:20)
    at initializeAppCheck (/app/.angular/prerender-root/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1498:5)
    at <anonymous> (app/.angular/prerender-root/c56c3be0-e454-4b23-bf7d-d028ecf276ec/node_modules/@angular/fire/fesm2022/angular-fire.mjs:216:44)
    at <anonymous> (/app/.angular/prerender-root/c56c3be0-e454-4b23-bf7d-d028ecf276ec/node_modules/@angular/fire/fesm2022/angular-fire.mjs:148:57)
    at _ZoneDelegate.invoke (/app/.angular/prerender-root/node_modules/zone.js/fesm2015/zone.js:368:26)
    at _Zone.run (/app/.angular/prerender-root/node_modules/zone.js/fesm2015/zone.js:129:43)
    at _NgZone.runOutsideAngular (/app/.angular/prerender-root/node_modules/@angular/core/fesm2022/core.mjs:1461
An unhandled exception occurred: document is not defined

Expected behavior

AngularFire should check if rendering on a browser before calling App Check code and RecaptchaV3 (which relies on document being available)

Actual behavior

No check is done, so when providing App Check, this above error occurs as soon as pre-rendering on the server happens and document is accessed but isn't available due to not running in a browser

jamesdaniels commented 6 months ago

It's older Angular but here's an example on how to use AppCheck with SSR https://github.com/angular/angularfire/blob/8157744c53e378c379b0bdedd480332b997f741a/samples/advanced/src/app/app.module.ts#L46

jjgriff93 commented 6 months ago

Thanks James, I've managed to work around it for now by using isPlatformServer()

provideAppCheck(() => {
      // Don't initialise AppCheck if running in server
      // Workaround for https://github.com/angular/angularfire/issues/3488
      const platformId = inject(PLATFORM_ID);
      if (isPlatformServer(platformId)) {
        return;
      }

      let provider: CustomProvider | ReCaptchaV3Provider;

      // Initialise AppCheck natively if running on iOS or Android
      if (Capacitor.isNativePlatform()) {
        // Set the web debug token to false if running on native
        globalThis.FIREBASE_APPCHECK_DEBUG_TOKEN = false;
        provider = new CustomProvider({
          getToken: () =>
            FirebaseAppCheck.getToken({
              forceRefresh: true
            }) as Promise<AppCheckToken>
        });
      } else {
        // Or use ReCAPTCHAv3 if running in web
        provider = new ReCaptchaV3Provider(
          environment.firebase.recaptchaSiteKey
        );
      }

      // Initialise AngularFire app check using provider
      const appCheck = initializeAppCheck(getApp(), {
        provider: provider
      });
      return appCheck;
    }),

Although now hitting a similar issue with Performance which the above doesn't seem to work for, so will raise that as a separate ticket

jjgriff93 commented 6 months ago

Raised in #3489