Reputation: 161
I have authGuard in my angular 17 project. I'm trying to dispatch my new token value to store but i got infinity loop. When i use this ligne in my canActivate code(i get infinity loop) :
this.store.dispatch(myAction.setAuthTokenValue({authToken: response.authToken,}));
here is my guard code:
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean | UrlTree> {
return this.authService.jwtToken$.pipe(
take(1),
switchMap(isAuthenticated => {
if (!isAuthenticated.isAuthenticated) {
return this.authService.getIfIsInAProdEnv().pipe(
map(isUseSAML => {
const isProdEnv = isUseSAML;
return this.redirectToLoginPage(isProdEnv);
})
);
} else if (isAuthenticated.token) {
// if (!this.isRenewToken) {
return this.authService.renewToken(isAuthenticated.token).pipe(
tap(response => {
if (response && response.authToken) {
this.isRenewToken = true;
console.log("tap")
this.store.dispatch(
MyActions.setAuthTokenValue({
authToken: response.authToken,
})
);
}
}),
switchMap(response => {
console.log("swith")
if (response && response.authToken) {
this.isRenewToken = false;
return this.checkAccess(route);
} else {
this.store.dispatch(MyActions.logout());
return of(this.redirectToLoginPage(false));
}
}),
catchError(() => {
this.store.dispatch(MyActions.logout());
return of(this.redirectToLoginPage(false));
})
);
} else {
return this.checkAccess(route);
}
// } else {
// return of(this.redirectToLoginPage(false));
// }
}),
catchError(() => {
this.store.dispatch(MyActions.logout());
return of(this.redirectToLoginPage(false));
})
);
}
redirectToLoginPage(isProdEnv: boolean) {
if (isProdEnv) {
return this.router.createUrlTree(['login/with-saml']);
} else {
return this.router.createUrlTree(['/login/with-email-id']);
}
}
Do have an idea to resolve this.
1 - I had to try to use this flag (i had commented in canActivate code you can see this // ) :
if (!this.isRenewToken) {
....
} else {
return of(this.redirectToLoginPage(false));
}
but this solution execute my renewToken request only once while i need to make renew request whenever user go to other path.
2 - I also tried : create tokenService:
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean | UrlTree> {
return this.authService.jwtToken$.pipe(
take(1),
switchMap(isAuthenticated => {
if (!isAuthenticated.isAuthenticated) {
return this.authService.getIfIsInAProdEnv().pipe(
map(isUseSAML => {
const isProdEnv = isUseSAML;
return this.redirectToLoginPage(isProdEnv);
})
);
} else if (isAuthenticated.token) {
return this.tokenService.isRenewingToken$.pipe(
take(1),
switchMap(isRenewing => {
if (!isRenewing) {
const token:string = isAuthenticated.token as string;
return this.tokenService.renewToken(token).pipe(
switchMap(response => {
if (response && response.authToken) {
return this.checkAccess(route);
} else {
this.store.dispatch(MyActions.logout());
return of(this.redirectToLoginPage(false));
}
}),
catchError(() => {
this.store.dispatch(MyActions.logout());
return of(this.redirectToLoginPage(false));
})
);
} else {
return this.checkAccess(route);
}
})
);
@Injectable({
providedIn: 'root',
})
export class TokenService {
private isRenewingTokenSubject = new BehaviorSubject<boolean>(false);
isRenewingToken$ = this.isRenewingTokenSubject.asObservable();
constructor(
private authService: AuthService,
private store: Store<MyState>
) {}
renewToken(token: string): Observable<any> {
this.isRenewingTokenSubject.next(true);
return this.authService.renewToken(token).pipe(
tap(response => {
if (response && response.authToken) {
this.store.dispatch(
MyAction.setAuthTokenValue({ authToken: response.authToken })
);
}
this.isRenewingTokenSubject.next(false);
}),
catchError(error => {
this.isRenewingTokenSubject.next(false);
throw error;
})
);
}
}
But it execute only once my request
Upvotes: 1
Views: 47