Giter Club home page Giter Club logo

Comments (9)

mauriciovigolo avatar mauriciovigolo commented on July 29, 2024 6

@findjonmos,

About this issue, I will share some code on how I handled this situation. But this is not needed in most of the cases, as for common situations the recommended way to get the config values is through the angular environment file.
To better show this common scenario, I've changed the example (keycloak-heroes) to instead of getting the keycloak config hardcoded, get from environment file.

Coming back to the original question of using a config file, the reason it was necessary to create an AppConfigService was that I needed to get some values from the webapp, but the initializer function was located in a separate library that we built to handle the company's common Angular components. So as the keycloak-angular initialization is done inside this common library I could not get the webapp environment values. Because of this, we create an assets/app-config.json file in every application which is loaded inside the AppConfigService.

I'm sharing a similar code, so you can take a look on the idea:

export function initializer(
  keycloak: KeycloakService,
  appConfig: AppConfigService,
): () => Promise<any> {
  return (): Promise<any> => {
    return new Promise(async (resolve, reject) => {
      let config: AppConfig;
      let env: EnvValues;

      try {
        config = await appConfig.getConfigValue();
      } catch (error) {
        // Here you should properly deal with the error
        reject();
        return;
      }

      try {
        await keycloak.init({
          config: {
            url: config.keycloakUrl,
            realm: config.realm,
            clientId: config.clientId
          },
          initOptions: {
            onLoad: 'login-required',
            checkLoginIframe: false
          }
        });

        resolve();
      } catch (error) {
        // Here you should properly deal with the error
        reject();
      }
    });
  };
}

Let me know if this answer helps you and if you succeed.

If you need any further assistance I'm available to help.

Thanks!

from keycloak-angular.

findjonmos avatar findjonmos commented on July 29, 2024 1

@mauriciovigolo Thank you very much for doing this. I will take some time soon to try and get this example working for me. Thanks very much :)

from keycloak-angular.

jacksloan avatar jacksloan commented on July 29, 2024 1

@findjonmos
Just to throw out another idea:

In our app we have a few init steps that depend on a config.json similar to your situation. It was starting to get a bit messy having everything in a single initializer so we decided to split things out.

Basically you can expose an observable in your config service. By subscribing to that observable in other dependent steps you can trigger them to load appropriately.

Complete example:
https://stackblitz.com/edit/angular-multiple-app-init-steps

The gist of it:

// first fake service exposes an observable to notify others of its completion
export function secondInitializerFn(firstFakeService: FirstFakeService, secondFakeService): () => Promise<any> {
    return (): Promise<any> => {
        return new Promise(async (resolve, reject) => {

          firstFakeService.configDoneSubject$
                .pipe(
                    tap(isLoaded => console.log('first config loaded: ' + isLoaded)),
                    skipWhile(isLoaded => isLoaded === false), // only trigger secondConfig load once firstConfig is done
                    switchMap(() => (from(secondFakeService.secondConfig()))))
                .subscribe(resolve, reject);
        });
    };
}

@NgModule({
...
...
...
  providers: [
    FirstFakeService,
    SecondFakeService,
    {
            provide: APP_INITIALIZER,
            useFactory: firstInitializerFn,
            multi: true,
            deps: [FirstFakeService]
    },
// we have to make the second service wait for the first service in the secondInitializerFn
    {
            provide: APP_INITIALIZER,
            useFactory: secondInitializerFn,
            multi: true,
            deps: [FirstFakeService, SecondFakeService]
    },
  ],
})
export class AppModule { }

from keycloak-angular.

mauriciovigolo avatar mauriciovigolo commented on July 29, 2024

Hello @findjonmos,

I've developed an angular components library at work and I does exactly what you are doing, loads an app-config.json file and uses part of the config data to initialize the keycloak.init. In our case the library is working as expected.

I think it may be the order of the calls or some kind of configuration you have in your app. Is there a way to share an example to reproduce the error?

from keycloak-angular.

findjonmos avatar findjonmos commented on July 29, 2024

Hey @mauriciovigolo , I will try to get you some source code to show what I was up to.

Is your example part of the repo here that I can look at?

from keycloak-angular.

mauriciovigolo avatar mauriciovigolo commented on July 29, 2024

Great @findjonmos,

The example in this repo doesn't have this functionality (load an app-config.json file). I can implement it and release a new version. I will take a look on this.

Tks!!

from keycloak-angular.

findjonmos avatar findjonmos commented on July 29, 2024

@mauriciovigolo Just wanted to come back to tell you that the solution you gave me worked nicely.
Thank you for your help.
I had a curiosity however in regards to how you handled any errors...I had an idea to try to force a redirect to a html page separate of angular since the project would not have booted up. Have you done something different?

from keycloak-angular.

mauriciovigolo avatar mauriciovigolo commented on July 29, 2024

@findjonmos, great that it helped!

About the way to handle errors, it depends in which layer you are talking about. If it is an error during the login process, Keycloak already bundles the error workflow and templates, so you could customize the template as mentioned at keycloak themes section.

If it is during the app initialization function (as mentioned above), you could also send the angular Router as a parameter, for example:

export function initializer(
  keycloak: KeycloakService,
  appConfig: AppConfigService,
  router: Router
): () => Promise<any> {
// ....
}

If any errors happen and your intention is to redirect to another route, you have the tools to do it.

from keycloak-angular.

mauriciovigolo avatar mauriciovigolo commented on July 29, 2024

@findjonmos, I'm closing this issue, since it seems to be solved. If you have any issues in the future we will be here to help. Thanks!

from keycloak-angular.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.