0

I am using Angular 7.2 MatDialog from Angular Material and rxjs 6. after the token expires, on the next http request, it brings the dialog up, but it does not submit the failed http request again. Although these suggestions are slightly different than what I need, I have tried this and this without luck. All that I need is that after the dialog closes, that it submit the failed request again, which is not happening at the moment. Can someone assist in finding what I am missing?

private refreshingToken: boolean = false;

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    return next.handle(this.setAuthorizationHeader(request))
        .pipe(
            catchError((error, caught) => {
                if (error instanceof HttpErrorResponse) {
                    if (error.status == 401) {
                        if (this.refreshingToken) {
                            return empty();
                        } else {
                            this.refreshingToken = true;
                            setTimeout(() => {
                                const dialog = this.authenticationService.OpenLoginDialog();
                                if (dialog) {
                                    const afterClosed$: Subscription = dialog
                                        .afterClosed()
                                        .pipe(
                                            switchMap(() => {
                                                return this.store.select(state => state.AccountState)
                                                .pipe(
                                                    map(data => data.accountLoggedIn)
                                                )
                                            }),
                                            switchMap((accountLoggedIn: boolean) => {
                                                if (accountLoggedIn) {
                                                    return next.handle(this.setAuthorizationHeader(request));
                                                }
                                            }),
                                            finalize(() => {
                                                this.refreshingToken = false;
                                                if (afterClosed$)
                                                afterClosed$.unsubscribe();
                                            })
                                        )
                                        .subscribe(afterClosedsubscribe => {
                                            console.log({afterClosedsubscribe: afterClosedsubscribe});
                                        });
                                }
                            });
                        }

                    }
                }
                return caught;
            })
        );
}

private setAuthorizationHeader(request: HttpRequest<any>): HttpRequest<any> {
    const token = this.tokenService.Get();
    if (token != null) {
        request = request.clone({
            setHeaders: {
                Authorization: `${token.tokenType} ${token.accessToken}`
            }
        });
    }
    return request;
}
WPalombini
  • 691
  • 9
  • 25

1 Answers1

0

I think the two switchMaps are the issue.

.pipe(
   switchMap(() => {
     return this.store.select(state => state.AccountState)
            .pipe(map(data => data.accountLoggedIn))
   }),
   switchMap((accountLoggedIn: boolean) => {
     if (accountLoggedIn) {
       return next.handle(this.setAuthorizationHeader(request));
     }
   }),
   finalize(() => {
     this.refreshingToken = false;
     if (afterClosed$)
        afterClosed$.unsubscribe();
   })
 )

Replace your above code with this.

.pipe(
   tap(() => {
     this.store.select(state => state.AccountState)
       .pipe(
         switchMap((data) => {
            if (data.accountLoggedIn) {
               return next.handle(this.setAuthorizationHeader(request));
            }
         }),
         finalize(() => {
           this.refreshingToken = false;
           if (afterClosed$)
              afterClosed$.unsubscribe();
         })
       );
   })
)

BTW, just a note. The way your doing this process, it will never execute the subscription of the original http request sent. You are using setTimeout from within interceptor. So, it will not return back to the original requester. Interceptor will simply end as soon as it reaches setTimeout.

If I am understanding it correctly, you are trying to recover your session when there is 401. If that's the case you can take a cue from this article and implement your use case accordingly. Let me know if you still need help.

Samarpan
  • 913
  • 5
  • 12