Problem with timing in token interceptor and authentication guard due to injected service

Currently, I am facing an issue where I need to retrieve URLs for the auth service hosted on AWS by reading a config.json file. In order to accomplish this, I created a config service that reads the config file and added it as a provider in app.module. Everything seemed to be working smoothly until I attempted to inject the config service into my authentication service.

Despite returning a promise and performing well elsewhere, the config service fails to provide the URL needed in the constructor of the authentication service. Since the authentication service relies on an oidc client, the URL is crucial at this stage. The authentication service is injected into an auth guard and a token interceptor which seem to be constructed earlier than a normal component, possibly leading to this issue.

I have exhausted all possible solutions but none have successfully retrieved the required URL. Thus, I am seeking assistance from any experienced developers who may have a solution. You can find a StackBlitz demo showcasing the problem here.

I have attempted various approaches such as checking if the config has loaded, delaying processing in the authentication service constructor, changing the promise to an observable, and even trying to read the config file directly in the constructor. However, none of these methods have resolved the issue despite spending over 3 days on this problem.

Below is the method in app.module calling the loadConfig method on my config service:

  return () => configService.loadConfig();
}

You can see it set as a provider here:

 providers: [
    ConfigService,
    {
      provide: APP_INITIALIZER,
      useFactory: initConfig,
      deps: [
        ConfigService
      ],
      multi: true
    },

The following snippet shows my config service call to load the file, which was functioning correctly until the introduction of the authentication service:

 public loadConfig(): Promise<any> {
    const promise = new Promise((resolve, reject) => {
      this.http.get('config.json')
        .toPromise()
        .then(
          res => { // Success
            this.config = JSON.parse(JSON.stringify(res));
            resolve();
          }
        );
    });
    return promise;
  }

Next, we have the code for the auth service:

constructor(@Inject(AuthenticationConfigService)
  private config: AuthenticationConfig,
    private router: Router,
    private configService: ConfigService,
    private http: HttpClient
  ) {
    const clientSettings = this.getClientSettings(config);
    this.manager = new UserManager(clientSettings);

    this.manager.getUser().then(user => {
      this.user = user;
    });

    this.redirectUrlKey = `redirectUrl:${this.manager.settings.authority}:${this.manager.settings.client_id}`;

    this.hookUpEvents();
  }

 private getClientSettings(config: AuthenticationConfig): UserManagerSettings {
    const url = window.location.origin;

    return {
      authority: this.configService.getAPIRoute('auth'), //this line fails
      // authority: config.authServer, //this line works as it has the url already defined
      client_id: config.clientId,
      redirect_uri: url + '/auth-callback',
      post_logout_redirect_uri: url,
      response_type: 'code',
      scope: config.scope,
      filterProtocolClaims: true,
      loadUserInfo: true,
      silent_redirect_uri: url + '/auth-silent'
    };
  }

In conclusion, I simply need a way to halt processing until the config file is fully loaded and all necessary values are available.

Answer №1

Utilize observables and subscriptions for efficient coding.

  private _loadStatus = new BehaviorSubject<boolean>(false);
  public loadStatus$ = this._loadStatus.asObservable();

Once the loading process is complete,

  this.data = JSON.parse(JSON.stringify(response));
  this._loadStatus.next(true);

Subscribe in the token interceptor to handle further actions.

   this.data.loadStatus$.subscribe(status => {
      if(status) {console.log(`TokenInterceptor: data loaded successfully`);}
   });

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having trouble with typecasting in Angular 9 after receiving an HTTP response?

When initializing my component, it fetches student information from an API. Here is the ngOnInit code for component-version1: ngOnInit(): void { if(!this.student) { this.studentsService.getStudentDetail(this.id).subscribe( (response: Stu ...

showing pop-up notification in Angular

I am utilizing the ngx-alert service to show an error message if the supplied credentials do not match any user account in my database. This is my current process: if (this.check.data.length == 0) { this.alert.danger('User does not exist' ...

javascript + react - managing state with a combination of different variable types

In my React application, I have this piece of code where the variable items is expected to be an array based on the interface. However, in the initial state, it is set as null because I need it to be initialized that way. I could have used ?Array in the i ...

Finding the IP address of a server in Angular: A Comprehensive Guide

Is there a way to dynamically retrieve the server host IP address in an Angular application launched with ng serve --host 0.0.0.0? This IP address will be necessary for communication with the backend server. As each coworker has their own unique IP addres ...

It appears that the crackling noise is being generated by AudioContext.decodeAudioData

I am currently in the process of developing an electron app that enables users to cut and rearrange multiple audio samples while seamlessly playing them back. The combined duration of these samples can exceed an hour, making it impossible to decode and sto ...

Exploring ways to simulate an event object in React/Typescript testing using Jest

I need to verify that the console.log function is triggered when the user hits the Enter key on an interactive HTMLElement. I've attempted to simulate an event object for the function below in Jest with Typescript, but it's not working as expecte ...

After defining Partial<T>, encountering an error trying to access an undefined property is unexpected

In my function, I am attempting to standardize certain values by specifying the whole function type as Partial. However, despite declaring the interaction variable as Partial Type, I keep encountering the error message saying "Cannot read property endTime ...

Is it possible to eliminate the port number in Angular 7?

Currently, I am utilizing Angular in conjunction with an ASP.Net Web application. One interesting observation I've made is that when I use ng build, the app builds and runs on a URL without any port number. However, if I run the app using ng serve, it ...

You cannot assign an array of 'Contact' objects to a single 'Contact' parameter

During the development process, I encountered an error while trying to add a new contact. The error message states: Error: src/app/contacts/contacts.component.ts:32:28 - error TS2345: Argument of type 'Contact[]' is not assignable to parameter o ...

Having trouble integrating jQuery into an Angular CLI project

I'm trying to incorporate jQuery into my angular project created with angular cli. I followed the instructions provided on this website: To begin, I installed jQuery by running: npm install --save jquery; Next, I added type definitions for jQ ...

Is it possible to assign an alternative name for the 'require' function in JavaScript?

To ensure our node module is executable and includes dependencies for requiring modules at runtime, we utilize the following syntax: const cust_namespace = <bin>_require('custom-namespace'); This allows our runtime environment to internal ...

Receiving an error while passing properties to a React component: "Property 'firstName' is not found on type 'Readonly<{}>'."

As a beginner in React, I need some patience I'm attempting to create a simple component where users can input their first and last names, update the values, and see them displayed after clicking a button. However, I keep encountering TypeScript comp ...

The lazy-loaded Angular module encountered an issue when attempting to access its child routes

I have been working on a dashboard app and currently, I've implemented two lazy loaded modules named AuthModule and AdminModule. The routing configuration in my app-routing-module.ts is as follows: const routes: Routes = [ { path: '&apo ...

Using Angular 2+ to make an http-get request with parameters

I am looking to create a GET method with multiple parameters. Currently, my example works with one parameter but I need to add another. In the backend code segment below, you can see where I am trying to pass the second parameter, 'created_by', b ...

Using Angular to pass an index to a pipe function

Currently, I am attempting to incorporate the *ngFor index into my pipe in the following manner: <td *ngFor="let course of courses | matchesTime:time | matchesWeekday:i ; index as i">{{course.courseName}}</td> This is how my pipe is structure ...

Exploring the Power of TextEncoding in TS 2.8 within the Angular 6 Environment

I'm facing a challenging issue while trying to import TextEncoding in TS 2.8. I have installed it using npm and attempted to import it like this: import { TextDecoder } from 'text-encoding'; Alternatively, import { } from 'text-encod ...

The Angular HTTP service dependency injection does not provide a return value

I am currently facing an issue with calling a service named MachineLearningService from my helper function. This service is supposed to receive arguments and return a response from an API. Strangely, after adding the HTTP dependency in my constructor, I am ...

The element of type 'OverridableComponent<LinkTypeMap<{}, "a">>' cannot be assigned to a 'ReactNode'

I'm currently working on a project where there's a component named ListItemTextStyle. Within that component, the prop type is defined as follows: import { LinkProps, ListItemButtonProps, } from '@mui/material'; type IProps = LinkP ...

Struggling to troubleshoot issues with asynchronous tasks in Angular? Encountering timeouts while waiting for elements on an Angular page? Learn

Edit: I have identified the source of my issue with guidance from @ernst-zwingli. If you are facing a similar error, one of his suggested solutions might be beneficial to you. My problem stems from a known Protractor issue itself. For those who suspect the ...

Adding client-side scripts to a web page in a Node.js environment

Currently, I am embarking on a project involving ts, node, and express. My primary query is whether there exists a method to incorporate typescript files into HTML/ejs that can be executed on the client side (allowing access to document e.t.c., similar to ...