I'm writing a route guard function using a signal from an auth service:
export const canActivate: CanActivateFn = ()=> {
console.log('guard called');
const authService = inject(HttpAuthService);
const router = inject(Router);
const loggedIn = computed<boolean>(() => {
const result = authService.user() !== null;
console.log('In computed: '+ result);
return result;
});
if (loggedIn()) {
console.log('can activate true');
return true;
} else {
console.log('can activate false');
return router.navigateByUrl('login');
}
};
The guard get's called but always return true even when the user is null after logout, Implementation of logout logs the new userState as expected null:
logout(): void {
this.userSignal.set(null);
console.log('Logout: '+ this.user())
}
So invoking logout logs "Logout: null" as expected;
but the guard always navigate to the login page. Logging shows that the computed block always return false despite the fact that the user signal from the auth service is updated on login and logout. I know this because the logout button is activated on successful login and disappear after clicking the logout button. This is the logout code:
@Component({
selector: 'app-logout',
standalone: true,
imports: [MatButtonModule, MatIconModule, NgIf],
template: `
<ng-container *ngIf="user()">
<button mat-icon-button (click)="onLogout()" >
<mat-icon>logout</mat-icon>
</button>
</ng-container>
`,
styles: ``
})
export class LogoutComponent {
user;
constructor(private authService: HttpAuthService) {
this.user = authService.user
}
onLogout() {
this.authService.logout();
}
}
So it looks like my guard is wrong, what am I missing? I also tryed to wrap the computed signal into an Observable with toObservable but that didn't change the result.
These assertions contradict with each other. But anyway login/logout are async, therefore, your guard may not have the actual user context by the time it is executed. Have you tried to return from the guard something like this?