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

Retrieve the attribute from a TypeScript union data type

Here is the structure that I am working with: export interface VendorState extends PaginationViewModel { vendors: CategoryVendorCommand[] | CategoryVendorCommand; } This is my model: export interface CategoryVendorCommand { id: string; name: str ...

ReactJS Error: The property 'hubConnection' is not defined on type 'JQueryStatic'

I am currently working with the Signalr library in React, but I keep encountering the following error: Property 'hubConnection' does not exist on type 'JQueryStatic'. Is there a solution to this issue? declare var window : any; import ...

The application of *ngComponentOutlet ngModuleFactory is unreliable when deployed in a production environment

While working on Angular 4, I utilized ngComponentOutlet to create dynamic components. In the development environment, my code functions properly but encounters issues in production. @Component({ selector: 'dynamic-detail', template: `<ng ...

Passing ng-content attributes from parent to child component in Angular 2

Would it be feasible to achieve this? My goal is to transmit a "hasfocus" variable from cjc-box using ng-content attributes to the cjc-input component. app.component.html <div cjc-box><div cjc-input></div></div> cic-box.componen ...

Issue encountered in Angular 2 while attempting to import TypeScript classes using a single file

Upon loading my Angular 2 application, I encountered the following error: EXCEPTION: Error: Uncaught (in promise): Unexpected piped value 'undefined' on the View of component 'DashboardComponent' An interesting observation is that by ...

Show varying mat-options based on the selected value of another mat-select

When selecting a continent from the first mat-select, only the countries belonging to that continent should appear in the second mat-select options. For example, if Asia is chosen as the continent, only Asian countries should be displayed. <div class=&q ...

What are the benefits of incorporating component A into component B as a regular practice?

I am considering creating an instance of Component A within Component B, but I'm unsure if this is a best practice in Angular or if it will just cause confusion. Component A: This component generates a modal window asking the user to confirm file de ...

Error in Angular production build due to Clean CSS failure

Encountering the following error during the code build process, any solutions? > ng build --prod --no-aot --base-href 92% chunk asset optimizationD:\myproject\node_modules\@angular\cli\node_modules\clean-css\lib&bsol ...

Mastering the art of theming components using styled-components and Material-UI

Can you integrate the Material-UI "theme"-prop with styled-components using TypeScript? Here is an example of Material-UI code: const useStyles = makeStyles((theme: Theme) => ({ root: { background: theme.palette.primary.main, }, })); I attemp ...

Searching for client using mqtt.js in Angular2 with Typescript yields no results

I am facing a unique issue while trying to incorporate the mqtt.js library into Angular 2 using TypeScript. Below is my app.component.ts file: import { Component } from '@angular/core'; import * as mqtt from 'mqtt'; @Component({ sel ...

Tips for delivering a variable to a React Native Stylesheet

Is there a way to pass a variable to the "shadowColor" property in my stylesheet from an array declared in the code above? I keep encountering a "Can't find name" error. Attempting to use a template literal has not resolved the issue. Any assistance w ...

Filtering Columns in Angular2 DataTable

Is there a way to filter an entire column, including the header and data, using Angular2 data-table? I have figured out how to filter the column data, but the header remains unaffected: https://stackblitz.com/edit/data-table-filter-columns UPDATE: Afte ...

Building a Docker image encounters an issue during the npm install process

Trying to utilize Docker with an Angular application, encountering issues during npm install within the Docker build process. When running npm install locally, no dependency errors or warnings occur. Error log from docker build: > [node 4/6] RUN npm i ...

Accepting a query string from an external server in Angular-Cli and Firebase Hosting: A step-by-step guide

When using location.href in browser side scripting, the submitted URL can be recorded successfully. For example, However, querying the URL from an external source, such as a PHP script on another server like <?php get_content('https://xxxx.firebas ...

Cricket score update features on the client side

Looking for assistance with client-side code development! I am currently working on an Android application using Ionic that involves live cricket scores. I have purchased a cricket API and understand how to connect to it using Node.js on the server side. ...

correct usage of getServerSideProps with Typescript in a next.js project using i18n

I'm encountering challenges with integrating next-i18next into a Typescript NextJS project. There are very few recent examples available for reference. I have successfully set up internationalized routing, but I am facing difficulties in configuring i ...

Hold off on progressing until the http.get request in Angular 4 has completed

Currently, I am in the process of creating a new registration form for an app using Ionic and utilizing ASP.Net(C#) for my API. My objective is to validate if a user already exists when the input blur event is triggered. However, I'm encountering an ...

Transmit information through a router connection

When attempting to pass data from one page to another routing page using [queryParams]="{'usd':usd, 'count' :country, 'name' :name}" through the routing button, it works perfectly fine but an error is displayed in my console. ...

Utilize CSS Styles with Angular 2 Component Selectors

I'm currently diving into Angular 2 and I've been pondering the idea of implementing CSS styles using the component selector in this manner: the component @Component({ selector: 'app', styleUrl: './local.css', te ...

Building a custom CellRenderer in AGGrid using TypeScript within a React environment

Currently, I am utilizing React along with TypeScript and attempting to create a custom CellRenderer in AGGrid. My code is structured like this: PriorityCellRenderer.tsx import React from 'react'; function PriorityCellRenderer(props:any) { co ...