I am creating a custom login service with AuthGuard
from Angular
. I have a SessionService
which have methods such a login()
or onUserLoggedIn()
which basically returns BehaviorSubject
with the current value of user status (logged in/not logged in). Based on this service I created an implementation of AuthGuard implements CanActivate
service. I call onUserLoggedIn
method and check the current value in subject. The problem here is that in login
method value is changed after the AuthGuard
call onUserLoggedIn
. Therefore in a first attempt I receive false value from BehaviorSubject but when I try the second time, I received a true value.
How can I change the implementation of those two services to achieve current value in a first attempt?
AuthGuard:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
: Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
console.log('auth');
return this.sessionService.onUserLoggedIn()
.pipe(
map(res => {
console.log('res', res);
return res;
}),
take(1),
tap(allowed => {
console.log(allowed);
if (!allowed) {
this.router.navigate(['/login']);
}
})
);
}
SessionService:
private isLoggedIn = new BehaviorSubject(false);
constructor(private apiService: ApiService) {
}
login(user: User): Observable<any> {
console.log('hello before');
return this.apiService.post(`${BASE_URL}/login`, user)
.pipe(
tap((token: Token) => {
this.isLoggedIn.next(true);
localStorage.setItem('token', token.token);
console.log('hello');
})
);
}
onUserLoggedIn() {
return this.isLoggedIn;
}
First attempt goes with printing value:
- SessionService.ts:19 hello before
- AuthGuard.ts:17 auth
- AuthGuard.ts:22 res false
- AuthGuard.ts:27 false
- SessionService.ts:25 hello
The second one (which I expect to be first):
- SessionService.ts:19 hello before
- AuthGuard.ts:17 auth
- AuthGuard.ts:22 res true
- AuthGuard.ts:27 true
- SessionService.ts:25 hello