angularfire icon indicating copy to clipboard operation
angularfire copied to clipboard

SSR => @firebase/auth: Auth (9.6.8): INTERNAL ASSERTION FAILED: Expected a class definition

Open ohabash opened this issue 3 years ago • 28 comments

Firebase:

"firebase": "^9.6.8",

AngularFire:

Angular CLI: 13.3.0
Node: 14.16.0
Package Manager: npm 6.14.11
OS: darwin x64

Angular: 13.2.5
... animations, cdk, common, compiler, compiler-cli, core, forms
... language-service, material, platform-browser
... platform-browser-dynamic, platform-server, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1303.0
@angular-devkit/build-angular   13.0.4
@angular-devkit/core            13.3.0
@angular-devkit/schematics      13.3.0
@angular/cli                    13.3.0
@angular/fire                   7.2.1
@angular/google-maps            13.3.0
@nguniversal/builders           13.0.2
@nguniversal/express-engine     13.0.2
@schematics/angular             13.3.0
ng-packagr                      13.2.1
rxjs                            6.6.7
typescript                      4.5.5

How to reproduce these conditions

  1. run habitat-commons:serve-ssr:development
  2. in my app browser and ssr server will build fine
  3. start ssr server node dist/apps/habitat-commons/server/main.js
  4. make a request to this server
  5. see errors below

First Error

 @firebase/auth: Auth (9.6.8): INTERNAL ASSERTION FAILED: Expected a class definition
Error: INTERNAL ASSERTION FAILED: Expected a class definition
    at debugFail (test_app/dist/apps/habitat-commons/server/main.js:317691:9)
    at debugAssert (test_app/dist/apps/habitat-commons/server/main.js:317704:5)
    at Module._getInstance (test_app/dist/apps/habitat-commons/server/main.js:317728:3)
    at new CompatPopupRedirectResolver (test_app/dist/apps/habitat-commons/server/main.js:315880:81)
    at _getInstance (test_app/dist/apps/habitat-commons/server/main.js:317736:14)
    at AuthImpl._initializeWithPersistence (test_app/dist/apps/habitat-commons/server/main.js:320082:37)
    at _initializeAuthInstance (test_app/dist/apps/habitat-commons/server/main.js:317817:8)
    at test_app/dist/apps/habitat-commons/server/main.js:325294:7
    at Component.instanceFactory (test_app/dist/apps/habitat-commons/server/main.js:325297:7)
    at Provider.getOrInitializeService (test_app/dist/apps/habitat-commons/server/main.js:327833:33)

i looked into the _getInstance mentioned in the callstack. it takes an arg that should be a class instance. hence the error.

Here is what _getInstance looked like in my ssr bootstrap (main.js)

function _getInstance(cls) {
  console.log('**((_getInstance 0))**', cls)
  debugAssert(cls instanceof Function, 'Expected a class definition');
  let instance = instanceCache.get(cls);

  if (instance) {
    debugAssert(instance instanceof cls, 'Instance stored in cache mismatched with class');
    return instance;
  }

  instance = new cls();
  instanceCache.set(cls, instance);
  return instance;
}

The log i added(see above) revealed that an error instead of a class was passed in the 3 rd time.see out put below

**((_getInstance 0))** [class InMemoryPersistence] { type: 'NONE' }
**((_getInstance 0))** [class CompatPopupRedirectResolver]
**((_getInstance 0))** FirebaseError: Firebase: Error (auth/operation-not-supported-in-this-environment).
    at createErrorInternal (test_app/dist/apps/habitat-commons/server/main.js:317665:38)
    at _createError (test_app/dist/apps/habitat-commons/server/main.js:317640:10)
    at Module.2485 (test_app/dist/apps/habitat-commons/server/main.js:325381:29)
    at __webpack_require__ (test_app/dist/apps/habitat-commons/server/main.js:545206:42)
    at Module.32562 (test_app/dist/apps/habitat-commons/server/main.js:325547:76)
    at __webpack_require__ (test_app/dist/apps/habitat-commons/server/main.js:545206:42)
    at Module.70092 (test_app/dist/apps/habitat-commons/server/main.js:315550:81)
    at __webpack_require__ (test_app/dist/apps/habitat-commons/server/main.js:545206:42)
    at Module.55776 (test_app/dist/apps/habitat-commons/server/main.js:500158:79)
    at __webpack_require__ (test_app/dist/apps/habitat-commons/server/main.js:545206:42) {
  code: 'auth/operation-not-supported-in-this-environment',
  customData: {}
}
[2022-03-17T20:12:59.002Z]  @firebase/auth: Auth (9.6.8): INTERNAL ASSERTION FAILED: Expected a class definition
ERROR Error: INTERNAL ASSERTION FAILED: Expected a class definition

of course all my servers and test requests are on local host...Do you know anything that can help me understand either error

@firebase/auth: Auth (9.6.8): INTERNAL ASSERTION FAILED: Expected a class definition

or

Firebase: Error (auth/operation-not-supported-in-this-environment)

Expected behavior

I expected to send a universal rendered view to the browser

Actual behavior

Firebase auth prevents universal from performing its task.

ohabash avatar Mar 17 '22 20:03 ohabash

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

google-oss-bot avatar Mar 17 '22 20:03 google-oss-bot

There seems to be a resolve in here. however I dont know how to apply it to my @angular/fire env

https://github.com/firebase/firebase-js-sdk/issues/5475#issuecomment-920211870

ohabash avatar Mar 17 '22 21:03 ohabash

any workaround for the above issue ?

ProSugu avatar Mar 19 '22 19:03 ProSugu

None that i have found but still working on it.

ohabash avatar Mar 20 '22 14:03 ohabash

Hello, hope you are doing well. I have same issue, If you found the solution, please let me know. thanks

joelgenaro avatar Mar 20 '22 18:03 joelgenaro

https://github.com/firebase/firebase-js-sdk/issues/5475#issuecomment-920211870

This seems to be the best lead however i have not figured out how to implement with @angular/fire

We had to use scully. But I will get start debugging this again soon.

ohabash avatar Mar 21 '22 22:03 ohabash

Also encountering this. I tried to use inMemoryPersistence but I still received the same error.

yharaskrik avatar May 18 '22 18:05 yharaskrik

I am encountering same issue. Any solution yet ?

I tried creating custom-webpack.config and added those resolve option but still it didn't work.

webpack.config.js

module.exports = {
  resolve: {
    mainFields: ["browser", "main"],
  },
};

Santoshah avatar Jun 01 '22 10:06 Santoshah

"firebase": "^9.8.1", I also struggle with this problem ... :/

kamstob avatar Jun 02 '22 18:06 kamstob

This will solve the issue for you if you are getting it when server side rendering (we are using Angular Universal)

provideAuth(() => {
            /*
             * This is a hack to get around the issue described in this thread:
             * https://github.com/firebase/firebase-js-sdk/issues/5475
             *
             * It has not been fixed and the webpack trick both did not work nor
             * was it simple to implement. What this does is it checks to see if it
             * is being SSR'd, if it is not then initialize firebase normally,
             * if it is then just "gets" the auth, which is essential a noop.
             */
            if (typeof document !== 'undefined') {
                return initializeAuth(getApp(), {
                    persistence: browserLocalPersistence,
                    popupRedirectResolver: browserPopupRedirectResolver,
                });
            }
            return getAuth(getApp());
        }),

yharaskrik avatar Jun 02 '22 18:06 yharaskrik

provideAuth

Thank you. May I ask you what the implementation for Angular 13 / Angularfire 7.3.0 should look like?

kamstob avatar Jun 03 '22 06:06 kamstob

provideAuth

Thank you. May I ask you what the implementation for Angular 13 / Angularfire 7.3.0 should look like?

What I shared above is working for me with angular 13 and angularfire 7

yharaskrik avatar Jun 03 '22 13:06 yharaskrik

Where this initializeAuth has to be mentioned ? I tried replacing all getAuth with this but it throws error saying initializeAuth can only be intialize one.

Santoshah avatar Jun 07 '22 03:06 Santoshah

Where this initializeAuth has to be mentioned ? I tried replacing all getAuth with this but it throws error saying initializeAuth can only be intialize one.

In our AppModule where firebase is initialized. You should only replace the initialization not all getauth calls.

image

yharaskrik avatar Jun 07 '22 04:06 yharaskrik

Where this initializeAuth has to be mentioned ? I tried replacing all getAuth with this but it throws error saying initializeAuth can only be intialize one.

In our AppModule where firebase is initialized. You should only replace the initialization not all getauth calls.

For me still not working. Any help ? image

import { AngularFireModule } from "@angular/fire/compat/";
import { AngularFireAuthModule } from "@angular/fire/compat/auth";
import { AngularFirestoreModule } from "@angular/fire/compat/firestore";
import { AngularFireMessagingModule } from '@angular/fire/compat/messaging';
import { AngularFireAuthGuardModule } from '@angular/fire/compat/auth-guard';
import { environment } from "../environments/environment";
import { provideFirebaseApp } from '@angular/fire/app';
import { provideAuth } from '@angular/fire/auth';
import { browserLocalPersistence, browserPopupRedirectResolver, getAuth, initializeAuth } from 'firebase/auth';

const { version: appVersion}=require('../../package.json');
const modules = []
if(environment.production) {
    modules.push(NgxHotjarModule.forRoot(environment.hotJarId, appVersion))
}
const firebaseApp = initializeApp(environment.firebase);
initializeFirestore(firebaseApp, { experimentalForceLongPolling: true });

const routerConfig: ExtraOptions = {
    scrollPositionRestoration: 'enabled',
    preloadingStrategy       : PreloadAllModules
};

@NgModule({
    declarations: [
        AppComponent,
        PreAssesmentComponent,
    ],
    imports: [
        BrowserModule.withServerTransition({ appId: 'serverApp' }),
        HttpClientModule,
        BrowserAnimationsModule,
        ReactiveFormsModule,
        FormsModule,
        //RouterModule.forRoot(appRoutes, routerConfig),
        AppRoutingModule,
        UserModule,
        CoreModule,
        LayoutModule,
        provideFirebaseApp(()=>initializeApp(environment.firebase)),
        provideAuth(() => {
            if (typeof document !== 'undefined') {
                return initializeAuth(getApp(), {
                    persistence: browserLocalPersistence,
                    popupRedirectResolver: browserPopupRedirectResolver,
                });
            }
            return getAuth(getApp());
        }),
        AngularFireModule.initializeApp(environment.firebase),
        AngularFireAuthGuardModule,
        AngularFireMessagingModule,
        AngularFireAuthModule,
        AngularFirestoreModule,
    ],

    bootstrap   : [
        AppComponent
    ],


})
export class AppModule
{
}

Santoshah avatar Jun 11 '22 05:06 Santoshah

Where this initializeAuth has to be mentioned ? I tried replacing all getAuth with this but it throws error saying initializeAuth can only be intialize one.

In our AppModule where firebase is initialized. You should only replace the initialization not all getauth calls.

For me still not working. Any help ? image

import { AngularFireModule } from "@angular/fire/compat/";
import { AngularFireAuthModule } from "@angular/fire/compat/auth";
import { AngularFirestoreModule } from "@angular/fire/compat/firestore";
import { AngularFireMessagingModule } from '@angular/fire/compat/messaging';
import { AngularFireAuthGuardModule } from '@angular/fire/compat/auth-guard';
import { environment } from "../environments/environment";
import { provideFirebaseApp } from '@angular/fire/app';
import { provideAuth } from '@angular/fire/auth';
import { browserLocalPersistence, browserPopupRedirectResolver, getAuth, initializeAuth } from 'firebase/auth';

const { version: appVersion}=require('../../package.json');
const modules = []
if(environment.production) {
    modules.push(NgxHotjarModule.forRoot(environment.hotJarId, appVersion))
}
const firebaseApp = initializeApp(environment.firebase);
initializeFirestore(firebaseApp, { experimentalForceLongPolling: true });

const routerConfig: ExtraOptions = {
    scrollPositionRestoration: 'enabled',
    preloadingStrategy       : PreloadAllModules
};

@NgModule({
    declarations: [
        AppComponent,
        PreAssesmentComponent,
    ],
    imports: [
        BrowserModule.withServerTransition({ appId: 'serverApp' }),
        HttpClientModule,
        BrowserAnimationsModule,
        ReactiveFormsModule,
        FormsModule,
        //RouterModule.forRoot(appRoutes, routerConfig),
        AppRoutingModule,
        UserModule,
        CoreModule,
        LayoutModule,
        provideFirebaseApp(()=>initializeApp(environment.firebase)),
        provideAuth(() => {
            if (typeof document !== 'undefined') {
                return initializeAuth(getApp(), {
                    persistence: browserLocalPersistence,
                    popupRedirectResolver: browserPopupRedirectResolver,
                });
            }
            return getAuth(getApp());
        }),
        AngularFireModule.initializeApp(environment.firebase),
        AngularFireAuthGuardModule,
        AngularFireMessagingModule,
        AngularFireAuthModule,
        AngularFirestoreModule,
    ],

    bootstrap   : [
        AppComponent
    ],


})
export class AppModule
{
}

You are still importing all of the angular fire modules from /compat. You should remove all of those and just use the provider functions introduced in v9.

(Except the auth guard module, just make sure you import that from that path that is not /compat).

These are the only Imports we have for firebase in our application:

import { getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app';
import { browserLocalPersistence, getAuth, initializeAuth, provideAuth } from '@angular/fire/auth';
import { AuthGuardModule } from '@angular/fire/auth-guard';
import { getMessaging, provideMessaging } from '@angular/fire/messaging';
import { browserPopupRedirectResolver } from '@firebase/auth';
import type { Environment } from '@trellis/shared/environment/client';

export function provideFirebase(environment: Environment) {
    return [
        provideFirebaseApp(() => initializeApp(environment.firebase)),
        provideAuth(() => {
            /*
             * This is a hack to get around the issue described in this thread:
             * https://github.com/firebase/firebase-js-sdk/issues/5475
             *
             * It has not been fixed and the webpack trick both did not work nor
             * was it simple to implement. What this does is it checks to see if it
             * is being SSR'd, if it is not then initialize firebase normally,
             * if it is then just "gets" the auth, which is essential a noop.
             */
            if (typeof document !== 'undefined') {
                return initializeAuth(getApp(), {
                    persistence: browserLocalPersistence,
                    popupRedirectResolver: browserPopupRedirectResolver,
                });
            }
            return getAuth(getApp());
        }),
        AuthGuardModule,
        provideMessaging(() => getMessaging()),
    ];
}

yharaskrik avatar Jun 11 '22 13:06 yharaskrik

Thanks @yharaskrik. It worked fine with modular firebase 9

We were in a process to update our firebase from 8 to 9. We had manage to remove compat version and run our application on modular version. Its working fine with Angular Universal + Angular version 14 and firebase 9

Santoshah avatar Jun 29 '22 03:06 Santoshah

😎😍😋😄🤔

On Tue, 28 Jun 2022 at 23:30, Santosh @.***> wrote:

Thanks @yharaskrik https://github.com/yharaskrik. It worked fine with modular firebase 9

We were in a process to update our firebase from 8 to 9. We had manage to remove compat version and run our application on modular version. Its working fine with Angular Universal + Angular version 14 and firebase 9

— Reply to this email directly, view it on GitHub https://github.com/angular/angularfire/issues/3181#issuecomment-1169495810, or unsubscribe https://github.com/notifications/unsubscribe-auth/AXJPNYZXTVZUWNZKZGV24ILVRO7OJANCNFSM5Q775GQA . You are receiving this because you commented.Message ID: @.***>

joelgenaro avatar Jun 29 '22 03:06 joelgenaro

Qui a une solution SSR 13 j'ai cauchemar pour ce probleme

aladjikane avatar Jul 01 '22 16:07 aladjikane

Qui a une solution SSR 13 j'ai cauchemar pour ce probleme

LIKEWISE.

does anyone have a solution already?

ElecTreeFrying avatar Jul 26 '22 20:07 ElecTreeFrying

Qui a une solution SSR 13 j'ai cauchemar pour ce probleme

LIKEWISE.

does anyone have a solution already?

Try my solution from above. It worked for me and others in the thread

yharaskrik avatar Jul 26 '22 20:07 yharaskrik

Qui a une solution SSR 13 j'ai cauchemar pour ce probleme

LIKEWISE. does anyone have a solution already?

Try my solution from above. It worked for me and others in the thread

@Santoshah the solution above doesn't work on my end.

const IMPORTS = [
  provideFirebaseApp(() => initializeApp(env.firebase)),
  provideStorage(() => getStorage(initializeApp(env.firebase))),
  // provideAuth(() => initializeAuth(initializeApp(env.firebase), {
  //   persistence: [ indexedDBLocalPersistence, browserLocalPersistence, browserSessionPersistence ],
  //   popupRedirectResolver: browserPopupRedirectResolver
  // }))
  provideAuth(() => {
    if (typeof document !== 'undefined') {
      return initializeAuth(getApp(), {
          persistence: browserLocalPersistence,
          popupRedirectResolver: browserPopupRedirectResolver,
      });
    }
    return getAuth(getApp());
  }),
];

ElecTreeFrying avatar Jul 26 '22 20:07 ElecTreeFrying

nevermind anyways, I already resolve the issue.

ElecTreeFrying avatar Jul 26 '22 22:07 ElecTreeFrying

Would you care to share what did you do to resolved the error. It might helped someone.

Santoshah avatar Jul 27 '22 01:07 Santoshah

Would you care to share what did you do to resolved the error. It might helped someone.

const IMPORTS = [
  provideFirebaseApp(() => initializeApp(env.firebase)),
  provideStorage(() => getStorage(getApp())),
  provideAuth(() => (typeof document === 'undefined' 
    ? getAuth(getApp())
    : initializeAuth(getApp(), {
        persistence: browserLocalPersistence,
        popupRedirectResolver: browserPopupRedirectResolver
      })
  ))
];

ElecTreeFrying avatar Jul 27 '22 08:07 ElecTreeFrying

Would you care to share what did you do to resolved the error. It might helped someone.

const IMPORTS = [
  provideFirebaseApp(() => initializeApp(env.firebase)),
  provideStorage(() => getStorage(getApp())),
  provideAuth(() => (typeof document === 'undefined' 
    ? getAuth(getApp())
    : initializeAuth(getApp(), {
        persistence: browserLocalPersistence,
        popupRedirectResolver: browserPopupRedirectResolver
      })
  ))
];

Where this initializeAuth has to be mentioned ? I am using angular 14 and firebase 9

PRUTHIRAJ97 avatar Apr 09 '23 12:04 PRUTHIRAJ97

Where this initializeAuth has to be mentioned ? I tried replacing all getAuth with this but it throws error saying initializeAuth can only be intialize one.

In our AppModule where firebase is initialized. You should only replace the initialization not all getauth calls.

For me still not working. Any help ? image

import { AngularFireModule } from "@angular/fire/compat/";
import { AngularFireAuthModule } from "@angular/fire/compat/auth";
import { AngularFirestoreModule } from "@angular/fire/compat/firestore";
import { AngularFireMessagingModule } from '@angular/fire/compat/messaging';
import { AngularFireAuthGuardModule } from '@angular/fire/compat/auth-guard';
import { environment } from "../environments/environment";
import { provideFirebaseApp } from '@angular/fire/app';
import { provideAuth } from '@angular/fire/auth';
import { browserLocalPersistence, browserPopupRedirectResolver, getAuth, initializeAuth } from 'firebase/auth';

const { version: appVersion}=require('../../package.json');
const modules = []
if(environment.production) {
    modules.push(NgxHotjarModule.forRoot(environment.hotJarId, appVersion))
}
const firebaseApp = initializeApp(environment.firebase);
initializeFirestore(firebaseApp, { experimentalForceLongPolling: true });

const routerConfig: ExtraOptions = {
    scrollPositionRestoration: 'enabled',
    preloadingStrategy       : PreloadAllModules
};

@NgModule({
    declarations: [
        AppComponent,
        PreAssesmentComponent,
    ],
    imports: [
        BrowserModule.withServerTransition({ appId: 'serverApp' }),
        HttpClientModule,
        BrowserAnimationsModule,
        ReactiveFormsModule,
        FormsModule,
        //RouterModule.forRoot(appRoutes, routerConfig),
        AppRoutingModule,
        UserModule,
        CoreModule,
        LayoutModule,
        provideFirebaseApp(()=>initializeApp(environment.firebase)),
        provideAuth(() => {
            if (typeof document !== 'undefined') {
                return initializeAuth(getApp(), {
                    persistence: browserLocalPersistence,
                    popupRedirectResolver: browserPopupRedirectResolver,
                });
            }
            return getAuth(getApp());
        }),
        AngularFireModule.initializeApp(environment.firebase),
        AngularFireAuthGuardModule,
        AngularFireMessagingModule,
        AngularFireAuthModule,
        AngularFirestoreModule,
    ],

    bootstrap   : [
        AppComponent
    ],


})
export class AppModule
{
}

You are still importing all of the angular fire modules from /compat. You should remove all of those and just use the provider functions introduced in v9.

(Except the auth guard module, just make sure you import that from that path that is not /compat).

These are the only Imports we have for firebase in our application:

import { getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app';
import { browserLocalPersistence, getAuth, initializeAuth, provideAuth } from '@angular/fire/auth';
import { AuthGuardModule } from '@angular/fire/auth-guard';
import { getMessaging, provideMessaging } from '@angular/fire/messaging';
import { browserPopupRedirectResolver } from '@firebase/auth';
import type { Environment } from '@trellis/shared/environment/client';

export function provideFirebase(environment: Environment) {
    return [
        provideFirebaseApp(() => initializeApp(environment.firebase)),
        provideAuth(() => {
            /*
             * This is a hack to get around the issue described in this thread:
             * https://github.com/firebase/firebase-js-sdk/issues/5475
             *
             * It has not been fixed and the webpack trick both did not work nor
             * was it simple to implement. What this does is it checks to see if it
             * is being SSR'd, if it is not then initialize firebase normally,
             * if it is then just "gets" the auth, which is essential a noop.
             */
            if (typeof document !== 'undefined') {
                return initializeAuth(getApp(), {
                    persistence: browserLocalPersistence,
                    popupRedirectResolver: browserPopupRedirectResolver,
                });
            }
            return getAuth(getApp());
        }),
        AuthGuardModule,
        provideMessaging(() => getMessaging()),
    ];
}

Where this initializeAuth has to be mentioned ?

PRUTHIRAJ97 avatar Apr 09 '23 13:04 PRUTHIRAJ97

I am in the same boat and trying to build ssr. We do not have provideFirebaseApp and provideAuth as we are on compat. We do not want to upgrade it to modules.

Is there any way to solve it while using compat.

We are on angular/[email protected] and "firebase": "^9.23.0",

We have this in our app.module.ts

imports: [
   AngularFireModule.initializeApp(environment.firebaseConfig),
    AngularFireDatabaseModule,
    AngularFirestoreModule,
    AngularFireAuthModule
    ]

Error that we are getting

[2023-10-01T13:31:31.585Z]  @firebase/auth: Auth (9.23.0): INTERNAL ASSERTION FAILED: Expected a class definition

indraraj26 avatar Oct 01 '23 14:10 indraraj26