I am implementing the auto-login concept with the PKCE Code Flow using this npm package. I tried following the documentation and example as best as I could. In my app.component.ts constructor I have the following:
if (this._oidcSecurityService.moduleSetup) {
this.doCallbackLogicIfRequired();
} else {
this._oidcSecurityService.onModuleSetup.subscribe(() => {
this.doCallbackLogicIfRequired();
});
}
In my ngOnInit I have the following:
ngOnInit(): void {
this._oidcSecurityService.getIsAuthorized().subscribe(auth => {
this.isAuthenticated = auth;
if (!this.isAuthenticated)
this._router.navigate(['/autologin']);
});
}
and in the method doCallbackLogicIfRequired() I have:
private doCallbackLogicIfRequired(): void {
this._oidcSecurityService.authorizedCallbackWithCode(window.location.toString());
}
And since the login page (and button) are located on the identity server (STS server), I have an auto-login component in my angular application which looks like this:
constructor(private _oidcSecurityService: OidcSecurityService) {
this.isAuthorizedSubscription = this._oidcSecurityService.onModuleSetup.subscribe(() => { this.onModuleSetup(); });
}
ngOnInit() {
if (this._oidcSecurityService.moduleSetup) {
this.onModuleSetup();
}
}
ngOnDestroy(): void {
this.isAuthorizedSubscription.unsubscribe();
}
private onModuleSetup() {
this._oidcSecurityService.authorize();
}
So my understanding and based on debugging the flow happens as follows:
- The user logs in from the STS server and gets redirected to the angular app and comes immediately to the app component
- The first thing it does in the app component is call the
doCallbackLogicIfRequiredMethod()and in turn, that calls theauthorizedCallbackWithCode()method. - Then it moves on to the ngOnInit (of the app component), which checks if the user is authorized, and since we are logging
in for the first time, he/she is not, so it routes over to the auto-login component which calls
the
oidcSecurityService.authorize()method.
So, now this is where I am having some issues and am not sure what is happening.
- So immediately after calling the
oidcSecurityService.authorize()method (int the auto-login.component) it goes right into the body of the subscribe of thegetIsAuthorized()method located in the app component ngOnInit. Why is it doing this? What is causing it to hit thegetIsAuthorized()again?
Here are the issues:
- The
getIsAuthorized()method is getting hit multiple times, and for some reason, it is always false, even after calling theauthorize()method from the auto-login component. - When I have the silent renew turned on, it seems to make things even worse and calls the
getIsAuthorized()even more times.
I am getting all strange issues/errors with identity server after this is happening and I assume it is because of this getIsAuthorized() method and maybe my understanding of where and when to actually use it.
Questions:
- For implementing this flow with an auto-login, am I taking the correct approach based on my example code?
- Can someone explain when the
getIsAuthorized()subscription is supposed to be called? Do other methods in the library maybe call it behind the scenes and that is why it is getting called multiple times for me? - I seem to be getting intermittent errors - invalid nonce and invalid state, why would this be
occuring (I read that this could happen when the
authorize()method is called more than once, but I only have one call to it in the auto-login.component)? - Just for my sanity and so I can understand the flow a little better, what is the purpose of the
authorizedCallbackWithCode()method where does it go, does it return to anywhere (is there an event handler for it i should be subscribing to)? - Also is the silent-renew logic supposed to call the
authorize()method? It seems to be doing that somewhere behind the scenes - I noticed that before i call theauthorize()method (from the auto-login component), theauthorizationResultCompleteevent handler is triggered without me ever callingauthorize(). Is this the expected behavior for the silent-renew, should it disrupt my application by doing this, I thought it should do everything behind the scenes (silently)?
I have been really struggling with this issue, if anyone has successfully implemented this flow using angular 2+ with this library, any help would be appreciated.
Thank You!