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.