Closed fraschizzato closed 8 months ago
@fraschizzato Did you find a solution for this issue? Have you been able to share the Keycloak Instance (KeycloakService) between the shell and the micro frontend?
@fraschizzato Did you find a solution for this issue? Have you been able to share the Keycloak Instance (KeycloakService) between the shell and the micro frontend?
No, I'm passing the token and other data with a shared service. In standalone mode every microfrontend has a separate keykloak init, in federated mode the first module is after the initial init module.
Hey @fraschizzato did you try to use an AuthGuard? Did you get it to find the token Values from the Injected KeycloakService?
Hi @fraschizzato, sorry for the late reply. I'm catching up on the issues and this one seems quite interesting and important to solve. Is it possible to create a simple example of the issue? Are you using something like Nx or similar? Thanks!
@Galileon-venta Not used AuthGuard, all the routes are catched and secured by keycloak auth.
@mauriciovigolo NX not used or similiar not used. I think the simpliest example is this: https://github.com/manfredsteyer/module-federation-plugin-example/tree/static It's the code of the example provided for module federation here: https://www.angulararchitects.io/en/aktuelles/the-microfrontend-revolution-part-2-module-federation-with-angular/
Anyway now I'm sharing token with a service in a custom system wide library. With that mode I can get keycloak security both in "Portal" mode and Standalone. The "Portal" is the main app, it starts from Main Module, inits the keycloak and store the token non the library. The Other Apps usually starts from a child module (called by the Portal) and get the token from the library. But, the other apps can also run indipently from their Main Module, that module also contain the keycloak init.
So: In standalone the sigle app starts itself and loads keycloak, in "Portal Mode" is loaded the single requested (child) module.
Thanks
Hi @mauriciovigolo, I'm using NX and a similiar issue (observe that reported error mention "is not a function" and in my case "is not a constructor") happend to me: ERROR TypeError: keycloak_js__WEBPACK_IMPORTED_MODULE_3__ is not a Constructor (refered line is where "keycloack.init()" is called.
In my case I observed a weird behaviour: error appear and then gone, I don't know how, but here is my history:
Enviroment
History
After setting all the stuff (see code) in Auth lib and Shell, first try it worked OK: when open the shell app, comunication with keycloak work and it redirect to base url with "error" parameter because user not authenticated.
After some changes in code (not related to the keycloak config stuff in the Auth lib), mentioned issue started to appear. Really I can't said wich changes had influence in the behaviour, was completelly unexpexted.
As I had no solution, I created the project again installing all library from cero. This time, the issue appeared since the first try
Then I tried to solve some compilation warnings (apparently not related to the issue):
I done following sequence:
{
...
"target": "ES2022",
...
}
"allowedCommonJsDependencies": [
"base64-js",
"js-sha256"
]
After that, everything started to work OK, issue has gone, really I don't know how and why.
Now (as always was) I have the keycloak stuff in the AuthModule defined in Auth lib generated with NX. In the Shell App I imported the AuthModule, the keycloak authentication checking is done perfectly, the user is redirected to the keycloak login page if necessary (I'm using onLoad: 'login-required') and after successfull login, user is returned back to shell app.
My scaffold and code Auth library
keycloak-initilizer.ts
import { KeycloakOptions, KeycloakService } from 'keycloak-angular';
import { environment } from '../../environments/environment';
export function initializer(keycloak: KeycloakService): () => Promise<boolean> {
const options: KeycloakOptions = {
config: environment.keycloak,
initOptions: {
//onLoad: 'check-sso',
onLoad: 'login-required',
checkLoginIframe: false
},
}
return () => keycloak.init(options);
}
shared-auth.modules.ts
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { KeycloakAngularModule, KeycloakService } from 'keycloak-angular';
import { initializer } from './keycloak-initializer';
import { AuthGuard } from './auth.guard';
import { AuthService } from './auth.service';
@NgModule({
imports: [CommonModule, KeycloakAngularModule],
providers: [
{
provide: APP_INITIALIZER,
useFactory: initializer,
multi: true,
deps: [KeycloakService]
},
AuthGuard,
AuthService,
]
})
export class AuthModule { }
Shell app scaffold
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { appRoutes } from './app.routes';
import { NxWelcomeComponent } from './nx-welcome.component';
import { AuthModule } from '@auth-lib/shared/auth';
@NgModule({
declarations: [AppComponent, NxWelcomeComponent],
imports: [
BrowserModule,
RouterModule.forRoot(appRoutes, { initialNavigation: 'enabledBlocking' }),
**AuthModule**
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
Hi @mauriciovigolo, as a follow up of the previous comment I would like to report that in my example, I'm stuck again after trying to run a micro-frontend different than the shell. The described error come back and no way to initialize connection with the keycloack. Look like a dependency injection problem. Please if you plan to solve this issue and need any specific information about the example, condition and enviroment, I'm available, I have an urgent need for this to work in the project I'm currently working.
Hey @cdonis, could you please provide me a codesanbox example with the problem described, so I could better look into this problem? Thank you!
Hi @mauriciovigolo, thank you very much for your attention. I already created a codesanbox with an example that trigger the error.
Example features:
This example never try to connect with keycloak server because during shell and sub-applications initialization, it trigger the mentioned error in line 19 of keycloak-initializer.ts (return () => keycloak.init(options).
As explained in my first post, during a trying where I was resolving following two compilation warnings,
the application runned OK with following behaviour:
then, when I tryied to run one of the subapplication directly (nx run users:serve), application stop working, i.e., error come back
Hi @cdonis, thank you so much for preparing an example! 🥇 I will dive into this issue today.
Hi @cdonis
I also am trying to use the keycloak angular in micro frontend along with Nx build systems , Webpack v5 and Module Federation . I also faced exactly the same issue. It worked initially for me, then I changed something(not related to keycloak) and getting starting the constructor error.
It points to this file
Versions used
Angular : 16.1.0 keycloak-angular : 14.0.0 keycloak-js : 21.1.2
Any help or tips to mitigate this issue at the earliest would be really helpful.
Hi @cdonis & @mauriciovigolo ! Any updates on this one? I'm facing exactly what @cdonis explained (and thanks again for the effort of making this reproductible). Did you find any workaround? I'm quite stuck here.
I didn't have the issue when using: Angular: 15.8 Nx: 15.8 keycloak-angular: 20.0.5 keycloak-js: 13.1.0
Now that I'm willing to upgrade to: Angular: 16.1.7 Nx: 16.6 keycloak-angular: 14.0.0 keycloak-js: 21.1.2
I'm facing this "keycloak_js__WEBPACK_IMPORTED_MODULE_5__ is not a constructor". Tried a lot of different things but I'm not able to make it work. As a last resort I'm thinking about skipping keycloak-angular and using directly keycloak-js even if it's quite a change as I have several angular remotes, I already have react remotes using it. If an investigation/fix/workaround is ongoing please let me know.
Thanks in advance and have a great day
I simply added the keycloak-js to the skip array you pass to the mfe webpack config (assuming you use the arhitects shareAll()). Don't share keycloak-js.
Hi @mauriciovigolo, any news about this issue?
Hello @mauriciovigolo any news/solutions? Or a workaround that will work? if you set it to skip, there are 2 different instances of keycloak in shell and mfe (doesn't solve the problem)
Finally I solved the error by just starting a new project from scratch, with the angular cli (ng new new-project) and copying the code to this new project. I don't know why
I did the same as @Ketec and it worked. I believe there is some sharing feature, like a singleton (I think), that might be affecting it.
i added this code as mentioned by @Ketec
shared: { ...shareAll( { singleton: true, strictVersion: true, requiredVersion: "auto", }, ["keycloak-js"] ), },
Unfortunately this does not work in my case. I get the following error
Why should we skip the keycloak-js library from being exported in the first place?
Fixed it by making changes to the webpack.config.js file
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const sharedMappings = new mf.SharedMappings();
sharedMappings.register(path.join(__dirname, "../../tsconfig.json"), [
/* mapped paths to share */
]);
module.exports = {
output: {
uniqueName: "log-analyzer",
},
plugins: [
new ModuleFederationPlugin({
shared: {
"@angular/core": { singleton: true, strictVersion: true },
"@angular/common": { singleton: true, strictVersion: true },
"@angular/router": { singleton: true, strictVersion: true },
...sharedMappings.getDescriptors(),
},
}),
sharedMappings.getPlugin(),
],
};
Not sure what it does, but it fixed the issue
Closing this issue, since it will be part of the major library improvements in #549.
None of the workarounds mentioned here works for me. Is there any known way for now to do this apart from waiting for an update to the keycloak library?
None of the workarounds mentioned here works for me. Is there any known way for now to do this apart from waiting for an update to the keycloak library?
Sure, you can't share keycloak via webpack module federation, but you can share it's instances (service, guard). I mean to create a library that will be shared as singleton, that library defines a service. Any piece (shell or micro) could initialize keycloak and save it's instance on the service as a property, accessible by other federated modules (shell or micro).
Hi @mauriciovigolo @cdonis @fraschizzato,
I see this issue has been closed. Was there a solution for this?
Hi, at this time I'm running keycloak-angular in a standalone app with the (working) following configuration/initialization:
Keycloak.init function:
AuthModule (first loaded):
If I try to share the keycloak-js in webpack (to federate the module) like this:
I'll get the following error (The share that causes the issue is
keycloak-js
):This is in the "shell" frontend, the one that is over all the other frontends. As I know the only way to share the same instance is by sharing the module. At this time I'm passing the token to the mfe via an external service library or through
localStorage
, the single frontend have an independent keycloak.init in the app.module (as in federation I'm passing the child module).Thanks
Versions.
keycloak-angular 12.1.0 keycloak-js 19.0.2
Repro steps.
Add the keycloak-js to the shares of module federation
Desired functionality.
I'd like to know if there's a way to share the keycloak instance to use widely the keycloak-angular and get all the features on the single microfrontends, firstly the AuthGuard.