Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto-Login with PKCE Code Flow using angular-auth-oidc-client

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:

  1. The user logs in from the STS server and gets redirected to the angular app and comes immediately to the app component
  2. The first thing it does in the app component is call the doCallbackLogicIfRequiredMethod() and in turn, that calls the authorizedCallbackWithCode() method.
  3. 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.

  1. So immediately after calling the oidcSecurityService.authorize() method (int the auto-login.component) it goes right into the body of the subscribe of the getIsAuthorized() method located in the app component ngOnInit. Why is it doing this? What is causing it to hit the getIsAuthorized() again?

Here are the issues:

  1. The getIsAuthorized() method is getting hit multiple times, and for some reason, it is always false, even after calling the authorize() method from the auto-login component.
  2. 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:

  1. For implementing this flow with an auto-login, am I taking the correct approach based on my example code?
  2. 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?
  3. 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)?
  4. 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)?
  5. 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 the authorize() method (from the auto-login component), the authorizationResultComplete event handler is triggered without me ever calling authorize(). 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!

like image 621
BryMan Avatar asked Jul 14 '19 02:07

BryMan


1 Answers

I think that you are a way ahead of what it's currently supported by most authentication servers. I will suggest that you implement the simple example that is 100% compatible with oidc pkce flow: authorization code flow + PKCE; I tried to implement the same pattern you described above; but that logic was designed for implicit flow and it seems that is not compatible with the response received from authentication server.

like image 54
Gi1ber7 Avatar answered Nov 18 '22 09:11

Gi1ber7