angularfire icon indicating copy to clipboard operation
angularfire copied to clipboard

Appcheck on Angular 17 does not work!

Open jonathansigg opened this issue 1 year ago • 2 comments

I tried to add AppCheck to my angular project. I have implemented angular 17 with angularfire 17. But somehow the appcheck can't be implemented. It is only a webapp. So no ios or andriod app is used here. Here is my package.json file:

{
  "name": "liveticker",
  "version": "1.1.5",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "start:munot": "ng serve --configuration munot",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test",
    "serve:ssr:liveticker": "node dist/liveticker/server/server.mjs",
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^17.0.0",
    "@angular/cdk": "^17.0.4",
    "@angular/common": "^17.0.0",
    "@angular/compiler": "^17.0.0",
    "@angular/core": "^17.0.0",
    "@angular/fire": "^17.0.0",
    "@angular/forms": "^17.0.0",
    "@angular/material": "^17.0.4",
    "@angular/platform-browser": "^17.0.0",
    "@angular/platform-browser-dynamic": "^17.0.0",
    "@angular/platform-server": "^17.0.0",
    "@angular/router": "^17.0.0",
    "@angular/ssr": "^17.0.3",
    "@fortawesome/angular-fontawesome": "^0.14.1",
    "@fortawesome/fontawesome-free": "^6.5.1",
    "@fortawesome/fontawesome-svg-core": "^6.4.2",
    "@fortawesome/free-brands-svg-icons": "^6.4.2",
    "@fortawesome/free-regular-svg-icons": "^6.4.2",
    "@fortawesome/free-solid-svg-icons": "^6.4.2",
    "@ng-bootstrap/ng-bootstrap": "^16.0.0",
    "@ngxs/store": "^3.8.2",
    "@popperjs/core": "^2.11.8",
    "bootstrap": "^5.3.2",
    "express": "^4.18.2",
    "immer": "^10.0.3",
    "rxjs": "~7.8.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.14.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^17.0.3",
    "@angular/cli": "^17.0.3",
    "@angular/compiler-cli": "^17.0.0",
    "@angular/localize": "^17.0.0",
    "@ngxs/devtools-plugin": "^3.8.2",
    "@types/express": "^4.17.17",
    "@types/jasmine": "~5.1.0",
    "@types/node": "^18.18.0",
    "jasmine-core": "~5.1.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.2.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.1.0",
    "prettier": "3.1",
    "typescript": "~5.2.2"
  }
}

And i have this in my app.config.ts

import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
import { provideAnimations } from '@angular/platform-browser/animations';
import { NgxsModule } from '@ngxs/store';
import { AppState } from './state/app.state';
import { NgxsReduxDevtoolsPluginModule } from '@ngxs/devtools-plugin';
import { firebaseModules } from './firebaseUtils';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideClientHydration(),
    importProvidersFrom(NgxsModule.forRoot([AppState])),
    importProvidersFrom(NgxsReduxDevtoolsPluginModule.forRoot()),
    provideAnimations(),
    provideAnimations(),
    ...firebaseModules,
  ],
};

I import the providers from firebaseUtils.ts (I have not coppied the firebaseConfig data)

import { importProvidersFrom, isDevMode } from '@angular/core';
import { provideFirebaseApp, initializeApp, getApp } from '@angular/fire/app';
import {
  provideAppCheck,
  initializeAppCheck,
  ReCaptchaEnterpriseProvider,
} from '@angular/fire/app-check';
import { provideAuth, getAuth } from '@angular/fire/auth';
import {
  provideFirestore,
  enableIndexedDbPersistence,
  getFirestore,
} from '@angular/fire/firestore';

...

const firebaseConfig = firebaseConfigProd;

let _firebaseModuls = [
  importProvidersFrom(provideFirebaseApp(() => initializeApp(firebaseConfig))),
  importProvidersFrom(provideAuth(() => getAuth())),
  importProvidersFrom(
    provideFirestore(() => {
      const firestore = getFirestore();
      try {
        enableIndexedDbPersistence(firestore)
          .then(() => {
            console.log('Firestore offline persistence enabled.');
          })
          .catch((error) => {
            if (error.code === 'failed-precondition') {
              console.log('Multiple tabs open, persistence cannot be enabled.');
            } else if (error.code === 'unimplemented') {
              console.log('IndexedDB is not available in this browser.');
            }
          });
      } catch (e) {
        console.error('Error enabling offline persistence', e);
      }
      return firestore;
    }),
  ),
  importProvidersFrom(
      provideAppCheck(() =>
        initializeAppCheck(getApp(), {
          provider: new ReCaptchaEnterpriseProvider(
            AppCheckCode,
          ),
          isTokenAutoRefreshEnabled: true,
        }),
      ),
    ),
];

export const firebaseModules = _firebaseModuls;

But i get an error message, if i implement Appcheck

ERROR ReferenceError: document is not defined
    at makeDiv (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1119:26)
    at initializeEnterprise (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1085:19)     
    at _ReCaptchaEnterpriseProvider.initialize (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1333:9)
    at _activate (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1543:20)
    at initializeAppCheck (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1498:5)        
    at eval (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@angular/fire/fesm2022/angular-fire.mjs:216:44)
    at eval (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@angular/fire/fesm2022/angular-fire.mjs:148:57)
    at _ZoneDelegate.invoke (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/zone.js/fesm2015/zone-node.js:368:26)
    at _Zone.run (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/zone.js/fesm2015/zone-node.js:129:43)
    at _NgZone.runOutsideAngular (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@angular/core/fesm2022/core.mjs:14608:28)
ReferenceError: document is not defined
    at makeDiv (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1119:26)
    at initializeEnterprise (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1085:19)     
    at _ReCaptchaEnterpriseProvider.initialize (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1333:9)
    at _activate (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1543:20)
    at initializeAppCheck (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1498:5)        
    at eval (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@angular/fire/fesm2022/angular-fire.mjs:216:44)
    at eval (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@angular/fire/fesm2022/angular-fire.mjs:148:57)
    at _ZoneDelegate.invoke (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/zone.js/fesm2015/zone-node.js:368:26)
    at _Zone.run (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/zone.js/fesm2015/zone-node.js:129:43)
    at _NgZone.runOutsideAngular (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@angular/core/fesm2022/core.mjs:14608:28)
14:06:40 [vite] Internal server error: document is not defined
      at makeDiv (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1119:26)
      at initializeEnterprise (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1085:19)   
      at _ReCaptchaEnterpriseProvider.initialize (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1333:9)
      at _activate (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1543:20)
      at initializeAppCheck (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@firebase/app-check/dist/esm/index.esm2017.js:1498:5)      
      at eval (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@angular/fire/fesm2022/angular-fire.mjs:216:44)
      at eval (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@angular/fire/fesm2022/angular-fire.mjs:148:57)
      at _ZoneDelegate.invoke (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/zone.js/fesm2015/zone-node.js:368:26)
      at _Zone.run (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/zone.js/fesm2015/zone-node.js:129:43)
      at _NgZone.runOutsideAngular (c:/Users/Jonat/Documents/GitHub/liveticker/node_modules/@angular/core/fesm2022/core.mjs:14608:28) (x2)  

How can i fix this problem? I really need this appcheck. And i don't want to go back to angular 16.

jonathansigg avatar Mar 19 '24 11:03 jonathansigg

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

google-oss-bot avatar Mar 19 '24 11:03 google-oss-bot

Where can i find a sample template?

jonathansigg avatar Apr 29 '24 12:04 jonathansigg

The trouble is that ReCaptchaEnterpriseProvider does not work on the server side & you are using Angular SSR. You need to provide an alternative implementation on the server, here's an example of using the Admin SDK https://github.com/angular/angularfire/blob/1302e3a73353cf495df2a54ae4e60f012d928d9a/samples/advanced/src/app/app.module.ts#L45

jamesdaniels avatar May 14 '24 19:05 jamesdaniels

Implementing Firebase App Check Debug Token in an Angular Application

Hello everyone,

I recently encountered a scenario where I needed to integrate Firebase App Check into my Angular application to enhance security. While testing, I noticed that the browser console was generating a debug token with the message "App Check debug token: XXXXXXXXXXXXX". This debug token is crucial for testing Firebase App Check locally before deploying the application.

To use this token, I followed these steps:

  1. I copied the debug token from the console.
  2. Then, I went to the Firebase Console, navigated to the App Check section, and under the "Manage debug tokens" option, I registered the new token.

After registering the token, I integrated it into my application by modifying the ReCaptchaEnterpriseProvider initialization in my code. Here’s how I updated my provider configuration:

const provider = new ReCaptchaEnterpriseProvider("XXXXXXXXXXXXX"); // Replace XXXXXXXXXXXXX with your registered debug token
return initializeAppCheck(undefined, { provider, isTokenAutoRefreshEnabled: true });

By replacing the placeholder with the actual debug token, I was able to test App Check more effectively in my development environment.

This process ensured that the App Check feature worked correctly without deploying it directly to production, allowing me to address any issues beforehand. Remember, the debug token is meant for testing purposes only and should be replaced with actual production credentials before deployment.

I hope this helps anyone looking to implement Firebase App Check in their projects!

delioribas avatar Jun 06 '24 16:06 delioribas