0

I am using ionic 7 and angular fire for authentication using firebase. Lot of code on the internet uses older way of app.module.ts which is no longer the way. So, i created a new firebase.module as below

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { initializeApp, provideFirebaseApp } from '@angular/fire/app';
import { provideAuth, getAuth } from '@angular/fire/auth';
import { provideFirestore, getFirestore } from '@angular/fire/firestore';

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: "XXXXX",
  ...
};


@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    provideFirebaseApp(
      () => initializeApp(firebaseConfig)), 
      provideAuth(() => getAuth()), 
      provideFirestore(() => getFirestore(),
  ),
  ],
  providers: []
})
export class FirebaseModule { }

The auth service file looks like below

//reference https://www.positronx.io/ionic-firebase-authentication-tutorial-with-examples/

import { Injectable, NgZone } from '@angular/core';
import {
  AngularFirestore,
  AngularFirestoreDocument,
} from '@angular/fire/compat/firestore';
import { AngularFireAuth } from '@angular/fire/compat/auth';
import { Router } from '@angular/router';
import { User } from './modal/user.modal';
import * as auth from 'firebase/auth';

@Injectable({
  providedIn: 'root'
})
export class AuthenticationServiceService {
  userData: any;

  constructor( public afStore: AngularFirestore,
    public ngFireAuth: AngularFireAuth,
    public router: Router,
    public ngZone: NgZone) {
      this.ngFireAuth.authState.subscribe((user) => {
        if (user) {
          this.userData = user;
          localStorage.setItem('user', JSON.stringify(this.userData));
          JSON.parse(localStorage.getItem('user') || '{}');
        } else {
          localStorage.setItem('user', null || '{}');
          JSON.parse(localStorage.getItem('user') || '{}');
        }
      });
     }

     // Returns true when user is looged in
  get isLoggedIn(): boolean {
    const user = JSON.parse(localStorage.getItem('user') || '{}');
    return user !== null && user.emailVerified !== false ? true : false;
  }
  // Returns true when user's email is verified
  get isEmailVerified(): boolean {
    const user = JSON.parse(localStorage.getItem('user') || '{}');
    return user.emailVerified !== false ? true : false;
  }
  // Sign in with Gmail
  GoogleAuth() {
    return this.AuthLogin(new auth.GoogleAuthProvider());
  }

  // Auth providers
  AuthLogin(provider: any) {
    return this.ngFireAuth
      .signInWithPopup(provider)
      .then((result) => {
        this.ngZone.run(() => {
          this.router.navigate(['dashboard']);
        });
        this.SetUserData(result.user);
      })
      .catch((error) => {
        window.alert(error);
      });
  }

  // Store user in localStorage
  SetUserData(user: any) {
    const userRef: AngularFirestoreDocument<any> = this.afStore.doc(
      `users/${user.uid}`
    );
    const userData: User = {
      uid: user.uid,
      email: user.email,
      displayName: user.displayName,
      photoURL: user.photoURL,
      emailVerified: user.emailVerified,
    };
    return userRef.set(userData, {
      merge: true,
    });
  }

  // Sign-out
  SignOut() {
    return this.ngFireAuth.signOut().then(() => {
      localStorage.removeItem('user');
      this.router.navigate(['login']);
    });
  }
  
}

And then i have tab1.page.ts as follow

import { FirebaseModule } from '../firebase/firebase.module';
import { AuthenticationServiceService } from '../authentication-service.service';

@Component({
  selector: 'app-tab1',
  templateUrl: 'tab1.page.html',
  styleUrls: ['tab1.page.scss'],
  standalone: true,
  imports: [IonicModule, CommonModule, FirebaseModule, FormsModule, ReactiveFormsModule],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class Tab1Page {
  constructor(public authService: AuthenticationServiceService) {}

the error i get is below

ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(Standalone[Tab1Page])[AuthenticationServiceService -> AuthenticationServiceService -> AuthenticationServiceService -> AuthenticationServiceService -> AngularFirestore -> InjectionToken angularfire2.app.options -> InjectionToken angularfire2.app.options]: 
  NullInjectorError: No provider for InjectionToken angularfire2.app.options!
NullInjectorError: R3InjectorError(Standalone[Tab1Page])[AuthenticationServiceService -> AuthenticationServiceService -> AuthenticationServiceService -> AuthenticationServiceService -> AngularFirestore -> InjectionToken angularfire2.app.options -> InjectionToken angularfire2.app.options]: 
  NullInjectorError: No provider for InjectionToken angularfire2.app.options!
    at NullInjector.get (core.mjs:7493:27)
    at R3Injector.get (core.mjs:7914:33)
    at R3Injector.get (core.mjs:7914:33)
    at injectInjectorOnly (core.mjs:618:33)
    at Module.ɵɵinject (core.mjs:622:60)
    at Object.AngularFirestore_Factory [as factory] (angular-fire-compat-firestore.js:584:102)
    at R3Injector.hydrate (core.mjs:8015:35)
    at R3Injector.get (core.mjs:7903:33)
    at injectInjectorOnly (core.mjs:618:33)
    at Module.ɵɵinject (core.mjs:622:60)
    at resolvePromise (zone.js:1211:31)
    at resolvePromise (zone.js:1165:17)
    at zone.js:1278:17
    at _ZoneDelegate.invokeTask (zone.js:406:31)
    at core.mjs:23896:55
    at AsyncStackTaggingZoneSpec.onInvokeTask (core.mjs:23896:36)
    at _ZoneDelegate.invokeTask (zone.js:405:60)
    at Object.onInvokeTask (core.mjs:24197:33)
    at _ZoneDelegate.invokeTask (zone.js:405:60)
    at Zone.runTask (zone.js:178:47)
Moblize IT
  • 1,140
  • 2
  • 18
  • 44
  • 1
    Your module is using "regular" paths. Meanwhile, in the service you use "compat". Maybe this is the reason. You provide and consume different providers. – Sergey Jun 27 '23 at 16:31

2 Answers2

2

I'm having this exact same problem and i got a lot of issues trying to solve it. Now i can login with Google popup but i'm having CORS issues not sure why. I think your problem is how you are trying to access to Auth. Found this example and it worked for me except for the CORS problem

import { Injectable, inject } from '@angular/core';
import { GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
import { Auth } from '@angular/fire/auth';
@Injectable({
  providedIn: 'root'
})
export class AuthService {
  private auth: Auth = inject(Auth);
  constructor() { }
  // Sign in using a popup.
  async signWithGoogle() {
    const provider = new GoogleAuthProvider();
    provider.addScope('profile');
    provider.addScope('email');
    const result = await signInWithPopup(this.auth, provider);

    const user = result.user;
    const credential = GoogleAuthProvider.credentialFromResult(result);
    const token = credential?.accessToken;
    console.log(user);
    console.log(token);
  }
}
Alex
  • 31
  • 2
0

Could you try creating an AuthenticationModule that provides an AuthenticationService and imports FirebaseModule, and then importing AuthenticationModule to Tab1Page instead of FirebaseModule?

barkin
  • 179
  • 2
  • 12