Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
ohabash opened this issue Mar 17, 2022 · 28 comments

Comments

@ohabash
Copy link

ohabash commented Mar 17, 2022

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.

@google-oss-bot
Copy link

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

@ohabash
Copy link
Author

ohabash commented Mar 17, 2022

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

firebase/firebase-js-sdk#5475 (comment)

@ProSugu
Copy link

ProSugu commented Mar 19, 2022

any workaround for the above issue ?

@ohabash
Copy link
Author

ohabash commented Mar 20, 2022

None that i have found but still working on it.

@joelgenaro
Copy link

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

@ohabash
Copy link
Author

ohabash commented Mar 21, 2022

firebase/firebase-js-sdk#5475 (comment)

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.

@yharaskrik
Copy link
Contributor

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

@Santoshah
Copy link

Santoshah commented Jun 1, 2022

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"],
  },
};

@kamstob
Copy link

kamstob commented Jun 2, 2022

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

@yharaskrik
Copy link
Contributor

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());
        }),

@kamstob
Copy link

kamstob commented Jun 3, 2022

provideAuth

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

@yharaskrik
Copy link
Contributor

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

@Santoshah
Copy link

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.

@yharaskrik
Copy link
Contributor

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

@Santoshah
Copy link

Santoshah commented Jun 11, 2022

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
{
}

@yharaskrik
Copy link
Contributor

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()),
    ];
}

@Santoshah
Copy link

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

@joelgenaro
Copy link

joelgenaro commented Jun 29, 2022 via email

@aladjikane
Copy link

aladjikane commented Jul 1, 2022

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

@ElecTreeFrying
Copy link

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

LIKEWISE.

does anyone have a solution already?

@yharaskrik
Copy link
Contributor

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

@ElecTreeFrying
Copy link

ElecTreeFrying commented Jul 26, 2022

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
Copy link

nevermind anyways, I already resolve the issue.

@Santoshah
Copy link

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

@ElecTreeFrying
Copy link

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
      })
  ))
];

@PRUTHIRAJ97
Copy link

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
Copy link

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 ?

@indraraj26
Copy link

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/fire@7.4.1 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests