Angular-auth-oidc-client: Indicate that isAuthenticated$ is out of NgZone

Created on 24 Mar 2021  Â·  6Comments  Â·  Source: damienbod/angular-auth-oidc-client

Is your feature request related to a problem? Please describe.
When using the library with NgRx Effects, using isAuthenticated$ in an effects throws an error if strictActionWithinNgZone is enabled

changedIsAuthenticated = createEffect(() => {
    return this.oidcSecurityService.isAuthenticated$.pipe(
      map((isAuthenticated) =>
        isAuthenticated
          ? AuthActions.isAuthenticated()
          : AuthActions.isNotAuthenticated()
      )
    );
  });

image

I think this problem comes out from this #965 #961

Describe the solution you'd like
Indicate that isAuthenticated$ is out of NgZone in the documentation

enhancement

Most helpful comment

https://github.com/cedbesafilm/test-oauth2-ngrx.git

I hope this help you @FabianGosebrink ✋
Of course you have to set sts and api in environment files
I hope I haven't forgotten anything, just in case ask me

All 6 comments

for the sake of knowledge

reference
https://medium.com/@naveen.kr/rxjs-custom-pipeable-operator-to-run-asynchronous-callbacks-inside-angular-zone-a49bd71c0bf6a

step to resolve the issue

  1. create a cutom pipeable operator
import { NgZone } from '@angular/core';
import { Observable } from 'rxjs';

export function enterZone(zone: NgZone) {
  return <T>(source: Observable<T>) =>
    new Observable<T>((observer) =>
      source.subscribe({
        next: (x) => zone.run(() => observer.next(x)),
        error: (err) => observer.error(err),
        complete: () => observer.complete(),
      })
    );
}
  1. in pipe use the custom operator to enter in the zone
  changedIsAuthenticated = createEffect(() => {
    return this.oidcSecurityService.isAuthenticated$.pipe(
      enterZone(this.ngZone),
      map((isAuthenticated) =>
        isAuthenticated
          ? AuthActions.isAuthenticated()
          : AuthActions.isNotAuthenticated()
      )
    );
  });

et voila 😄

Hey, just to let me understand this, AFAIS: In a case of a silent renew the isAuthenticated$ is emitted _outisde_ the ngZone and you have to manually get back in again to trigger CD and avoid the error message, is that correct?

Hey, just to let me understand this, AFAIS: In a case of a silent renew the isAuthenticated$ is emitted _outisde_ the ngZone and you have to manually get back in again to trigger CD and avoid the error message, is that correct?

Yes isAuthenticated$ is emitted outside ngZone (or at least that's what ngrx says), userDatadoesn't seem to have the same kind of 'problem'
Honestly, I have not manually tested how the CD reacts in a component, because I was working directly within the effects of Ngrx (little OT here i think 😄)

Thanks for the quick response. userData does not step out of the ngZone. I would love to get the ngZone.run() _inside_ the lib that you do not have to do the hack...

Can you provide a small sample repo _WITH_ the error? You can take a config from the samples. Would that be possible?

https://github.com/cedbesafilm/test-oauth2-ngrx.git

I hope this help you @FabianGosebrink ✋
Of course you have to set sts and api in environment files
I hope I haven't forgotten anything, just in case ask me

Hey, no that one helped. Thank you. So with the PR I just added we are hooking back into the ngzone again. I tested that the isAuthenticated$ event is only fired when the value changes and the error is not coming up with your repo and the tests. I also tested that the app is stable again, receiving true when using

export class AppModule {
  constructor(applicationRef: ApplicationRef) {
    applicationRef.isStable
      .pipe(tap((isStable) => console.log(`ApplicationRef::stable`, isStable)))
      .subscribe();
  }
}

So if @damienbod releases the next time, you do not need to hook back into the ngzone manually again.

Was this page helpful?
0 / 5 - 0 ratings