0

I have two angular projects:

  • Main app
  • Webcomponent (angular elements)

Webcomponent is used in the main app. Both are using angularfire for executing Firebase functions, working with Firestore and more.

Also I am enforcing verified request to the Functions and Firestore by AppCheck.

The web component needs to work separately. To be able to request Firebase servers I need to provide the AppCheck in both projects like this:

@NgModule({
  ...
  imports: [
    ...

    provideAppCheck(() => initializeAppCheck(getApp(), {
      provider: new ReCaptchaV3Provider(environment.firebase.appCheck.recaptcha3SiteKey),
      isTokenAutoRefreshEnabled: environment.firebase.appCheck.isTokenAutoRefreshEnabled,
    }))

    ...
  ],
  ...
})

This works just fine when webcomponent is not included in the main app. However when so, the AppCheck is initialized two times and it throws an error:

Unhandled Promise rejection: reCAPTCHA has already been rendered in this element ; Zone: <root> ; Task: Promise.then ; Value: Error: reCAPTCHA has already been rendered in this element

So the webcomponent needs to check if appcheck already exists in document and add it only if it does not. I tried to work with appCheckInstance$ but that is an observable and provideAppCheck requires only AppCheck type. When I try to move provideAppCheck to component which would handle the logic, I get an error saying that calling it can not be done outside module:

Either AngularFireModule has not been provided in your AppModule (this can be done manually or implictly using
provideFirebaseApp) or you're calling an AngularFire method outside of an NgModule (which is not supported).

I have no other ideas how this could be done other than building two webcomponents (one with appcheck, other without), but thats just not an option.

1 Answers1

0

It turned out that the problem was elsewhere. I thought that conditional appcheck loading would help, but it didn't, because then angularfire(in webcomponent) didn't use the appcheck that the main app initialized. And hence connections to firebase were blocked (as if there was no appcheck initialized).

Solution I've figured out that works:

In webcomponent initialize all firebase services under different name. So instead of:

@NgModule({
  ...
  imports: [
    ...
    provideFirebaseApp(() => initializeApp(environment.firebase)),
    provideFirestore(() => getFirestore(getApp())),
    provideAppCheck(() => initializeAppCheck(getApp(), {
      provider: new ReCaptchaV3Provider(environment.firebase.appCheck.recaptcha3SiteKey),
      isTokenAutoRefreshEnabled: environment.firebase.appCheck.isTokenAutoRefreshEnabled,
    })),
    ...
  ],
  ...
})

do:

@NgModule({
  ...
  imports: [
    ...
    provideFirebaseApp(() => initializeApp(environment.firebase, 'webcomponent-app')),
    provideFirestore(() => getFirestore(getApp('webcomponent-app'))),
    provideAppCheck(() => initializeAppCheck(getApp('webcomponent-app'), {
      provider: new ReCaptchaV3Provider(environment.firebase.appCheck.recaptcha3SiteKey),
      isTokenAutoRefreshEnabled: environment.firebase.appCheck.isTokenAutoRefreshEnabled,
    })),
    ...
  ],
  ...
})

This will initialize two instances (one for main app, other for webcomponent) with different names. And now initializing two appchecks is not problematic.