ebg11
ebg11

Reputation: 1046

How to initialise Firebase App Check in Angular

I was wondering how can i initialise firebase app check using angular.

I am using angular fire but I am not sure how to initalise firebase app check before using any of the services

the docs have this

Add the following initialization code to your application, before you access any Firebase services.

firebase.initializeApp({
  // Your firebase configuration object
});

const appCheck = firebase.appCheck();
// Pass your reCAPTCHA v3 site key (public key) to activate(). Make sure this
// key is the counterpart to the secret key you set in the Firebase console.
appCheck.activate('abcdefghijklmnopqrstuvwxy-1234567890abcd');

But how can this be done in app module. Currently i import angular fire like so

@NgModule({
  declarations: [
   ...
  ],
  imports: [
    AngularFireModule.initializeApp(environment.firebaseConfig),
  ],
]

Update:

I know this is probably not yet part of the angular fire library due to how new firebase app-check is but I have noticed there is a native firebase library https://www.npmjs.com/package/@firebase/app-check

I am happy for this to be used (e.g. somehow overriding the native firebase js object) as long as the code is able to apply it in the correct location before any services are called and that it gives no compilation errors in typescript

For reference my versions are as follows:

Angular: 10.2.5

Firebase: 8.6.0

AngularFire: 6.1.5

The debug localhost version must also work

Upvotes: 5

Views: 5254

Answers (3)

Jack
Jack

Reputation: 10623

You could also achieve this with a service and interceptor (code below). The service should probably add some kind of caching of tokens (shorter TTLs for more security, longer TTLs for lower costs). See Enable App Check with reCAPTCHA Enterprise in web apps for more detail.

To keep the service implementation simple, the token caching code is not included.

The service holds the logic to get a token using App Check.

import { Injectable } from '@angular/core';
import { FirebaseApp, initializeApp } from 'firebase/app';
import { AppCheck, AppCheckTokenResult, getToken, initializeAppCheck, ReCaptchaEnterpriseProvider } from 'firebase/app-check';
import { environment } from 'src/environments/environment';

@Injectable({
  providedIn: 'root'
})
export class AppCheckService {

  app: FirebaseApp;
  appCheck: AppCheck;

  constructor() {
    this.app = initializeApp(environment.firebase);

    // Create a ReCaptchaEnterpriseProvider instance using reCAPTCHA Enterprise.
    this.appCheck = initializeAppCheck(this.app, {
      provider: new ReCaptchaEnterpriseProvider(environment.recaptchaEnterpriseKey),
      isTokenAutoRefreshEnabled: true // Set to true to allow auto-refresh.
    });
  }


  async getToken(): Promise<AppCheckTokenResult | undefined> {
    let appCheckTokenResponse;
    try {
      appCheckTokenResponse = await getToken(this.appCheck);
    } catch (err) {
      // TODO: Handle any errors if the token was not retrieved.
      return;
    }
    return appCheckTokenResponse;
  }
}

This service can then be used by an interceptor which is responsible for adding a X-Firebase-AppCheck HTTP header with the token.

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { AppCheckTokenResult } from '@firebase/app-check';
import { from, Observable } from 'rxjs';
import { switchMap, take } from 'rxjs/operators';
import { environment } from '../../environments/environment';
import { AppCheckService } from '../services/app-check.service';

@Injectable()
export class AppCheckInterceptor implements HttpInterceptor {

    constructor(private readonly appCheckService: AppCheckService) { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        return from(this.appCheckService.getToken()).pipe(
            take(1), // See https://stackoverflow.com/a/60196923/828547.
            switchMap((token: AppCheckTokenResult | undefined) => {
                if (token) {
                    request = request.clone({
                        setHeaders: { "X-Firebase-AppCheck": token?.token },
                    });
                }
                return next.handle(request);
            }),
        );
    }
}

You will need to add recaptchaEnterpriseKey to your Angular environment files

export const environment = {
  recaptchaEnterpriseKey: '6LfGni324khkjh324hkDSFsdfSfsdm',
};

And finally add the interceptor to your app.module.ts file

providers: [
 {
      provide: HTTP_INTERCEPTORS,
      useClass: AppCheckInterceptor,
      multi: true,
 },
]

Upvotes: 5

KingDarBoja
KingDarBoja

Reputation: 1053

Do this:

// firebase-initialization.ts
import firebase from 'firebase/app';
import 'firebase/app-check';

// Environment Config
import { environment } from './path/to/environments';

const app = firebase.initializeApp(environment.firebase);
const appCheck = app.appCheck()
appCheck.activate('');

Then import the file in the app module as:

import "firebase-initialization"

Upvotes: 8

Glauber
Glauber

Reputation: 602

I had to use the event DOMContentLoaded to make app check work with my angularJS app, maybe you can try it:

window.addEventListener('DOMContentLoaded', () => {
  var appCheck = firebase.appCheck()
  appCheck.activate('captchatokenid')
})

Upvotes: 1

Related Questions