Skip to content

AppCheck Build Error During Prerender for Angular SSR  #3128

Description

@asithade

Version info

Angular: 13.0.3

Firebase: 9.6.4

AngularFire: 7.2.0

Other (e.g. Ionic/Cordova, Node, browser, operating system): Node 14

How to reproduce these conditions

Steps to set up and reproduce

After setting up AppCheck as such:

import { initializeAppCheck, provideAppCheck, ReCaptchaV3Provider } from '@angular/fire/app-check';

    provideAppCheck(() => initializeAppCheck(getApp(), { provider: new ReCaptchaV3Provider(environment.recaptchaSiteKey), isTokenAutoRefreshEnabled: true })),

I am able to serve my application with both yarn server and yarn dev:ssr and I'm able to load the site with AppCheck seemingly working. However, when I try to run yarn prerender, I get the following error:

Unhandled Promise rejection: document is not defined ; Zone: <root> ; Task: Promise.then ; Value: ReferenceError: document is not defined

Activity

  1. google-oss-bot commented on Jan 21, 2022

    @google-oss-bot

    This issue does not seem to follow the issue template. Make sure you provide all the required information.

  2. ribalnasr commented on Feb 21, 2022

    @ribalnasr

    Did you find a solution for this?

  3. ribalnasr commented on Feb 21, 2022

    @ribalnasr

    Here's my workaround for now...

    I created a service:

    @Injectable({
        providedIn: 'root'
    })
    export class RecaptchaBrowser {
    
        constructor(
            @Inject(PLATFORM_ID) private platformId: string
        ) { }
    
        provider(siteKey: string) {
            return isPlatformBrowser(this.platformId)
                ? new ReCaptchaV3Provider(siteKey)
                : new CustomProvider({
                    getToken: () => new Promise(() => { })
                })
        }
    }
    

    and then I import the AppCheck module as follows:

        provideAppCheck((injector) => initializeAppCheck(getApp(), {
          provider: injector.get(RecaptchaBrowser).provider(environment.recaptchaSiteKey),
          isTokenAutoRefreshEnabled: true
        })),
    
    

    This will skip the ReCaptchaV3Provider for server-side rendering and import it only in the browser.

  4. miikaeru commented on Mar 19, 2022

    @miikaeru

    I have the same issue. Is AppCheck not supported in Angular Universal?

  5. posva commented on Nov 30, 2022

    @posva

    There is actually an example at https://github.com/angular/angularfire/blob/master/samples/advanced/src/app/app.module.ts#L47-L57

    You need to use the admin sdk on server

  6. MawRojas commented on Jan 25, 2023

    @MawRojas

    Has anyone found a solution for this? The closest I've gotten is to check if the app is being checked on the server; if it is, then I create a custom provider similar to @ribalnasr.
    The issue with this is that it only works if app check is not enforced on Cloud Firestore. Once it is actually enforced, the request from the server will be rejected, which is to be expected.
    I haven't found a way to generate valid recaptchav3 token on the sever. If there's a way to create this token then we should be able to use it in a custom provider for app check.

  7. Abdulali97 commented on Dec 19, 2023

    @Abdulali97

    I have the same issue: Angular SSR v17

  8. Abdulali97 commented on Dec 19, 2023

    @Abdulali97

    this works for me

    app config

    const FIREBASE_ADMIN = new InjectionToken<app.App>('firebase-admin');
    
    export function initializeAppCheckFactory(
      platformId: Object,
      injector: Injector
    ) {
      if (isPlatformBrowser(platformId)) {
        const admin = injector.get<app.App | null>(FIREBASE_ADMIN, null);
        if (admin) {
          const provider = new CustomProvider({
            getToken: () =>
              admin
                .appCheck()
                .createToken(environment.firebase.appId, { ttlMillis: 604_800_000 })
                .then(({ token, ttlMillis: expireTimeMillis }) => ({
                  token,
                  expireTimeMillis,
                })),
          });
          return initializeAppCheck(undefined, {
            provider,
            isTokenAutoRefreshEnabled: false,
          });
        } else {
          const provider = new ReCaptchaEnterpriseProvider(
            environment.recaptchaEnterpriseSiteKey
          );
          return initializeAppCheck(undefined, {
            provider,
            isTokenAutoRefreshEnabled: true,
          });
        }
      }
      return undefined;
    }
    
    export const appConfig: ApplicationConfig = {
      providers: [
        {
          provide: AppCheck,
          useFactory: (platformId: Object, injector: Injector) =>
            initializeAppCheckFactory(platformId, injector),
          deps: [PLATFORM_ID, Injector],
        },
        {
          provide: FIREBASE_OPTIONS,
          useValue: environment.firebase,
        },
        provideClientHydration(),
        provideAnimationsAsync(),
        provideRouter(
          appRoutes,
          withEnabledBlockingInitialNavigation(),
          withViewTransitions()
          // withDebugTracing()
        ),
        importProvidersFrom(
          provideFirebaseApp(() => initializeApp(environment.firebase)),
          provideAuth(() => getAuth())
        ),
        provideStore({ auth: authReducer }),
        provideEffects([AuthEffects]),
      ],
    };

    and Injecting AppCheck into AppComponent ensures initialization in a client-side context

    export class AppComponent{
      constructor(
        private router: Router,
        private authFacade: AuthFacade,
        private appCheck: AppCheck,
      ) {} 
  9. hittten commented on Dec 23, 2023

    @hittten

    https://github.com/angular/angularfire/blob/master/samples/advanced/src/app/app.module.ts#L47-L57

    It seems like a good solution but it has a dependency on the "firebase-admin" package. In my case, I just want to configure the app-check correctly but I don't need the firebase-admin.

    It would be great if angular-fire provided a correct example of recommended implementation for AppCheck with SSR and prerender

  10. added
    comp: ssrServer-side rendering, hydration, @angular/ssr interop.
    type: bugDefect: expected behavior doesn't happen.
    on Sep 25, 2026
  11. added a commit that references this issue on Sep 27, 2026
    84a8a51
  12. added this to the 21.0.0-rc.2 milestone on Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    comp: app-checkApp Check (src/app-check).comp: ssrServer-side rendering, hydration, @angular/ssr interop.type: bugDefect: expected behavior doesn't happen.version: legacy (v7-v16)Targets the older modular API (roughly v7-v16).

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions