0
votes

I am using BehaviorSubject to store user info on login. For some weird reason, the user info returned by BehaviorSubject is null in AuthGuard that gets activated for my endpoint. Please help me understand what am I missing.

I have already tried to return the subject as observable, subcribe to the subject, ReplaySubject. Nothing seems to work and the user info is always null in auth guard. I have moved the AuthService provider declaration between app module and the service component. That also didn't help. Until the call goes to auth guard, the flow is normal where the user info is set. As soon as the auth guard is called, the user info is lost.

user reg: This is step where user logs in

 onSubmit() {
    this.document.location.href = environment.callbackUrl;
  }

login component: This component sets the user info

this.authService.setUserInfo(user);
if (user.id_token!=null && user.role!=null && user.isLoggedIn){
  this.router.navigate(['/view-main/datalogger-list']);
}

auth service

userSubject: BehaviorSubject<UserInfo> = new BehaviorSubject<UserInfo>(null);

setUserInfo(user: UserInfo){
  if(user && user !=null){
    this.userSubject.next(user);
  }
}

getUserInfo() {
    return this.userSubject.asObservable();
  }

auth guard: here the user info is null

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    debugger
    let userInfo:UserInfo;

    this.authService.getUserInfo().subscribe(user => {
      console.log('Evaluating in auth guard');
      console.log('User: ', user);
      //if user is logged in and role info is available from database.
      if(user && user!=null 
          && user.role!=null && user.role.trim().length>0 
          && user.wwid!=null && user.wwid.trim().length>0){
        // allow user
        userInfo = user;
        return true;
      }
      // TO-DO user logged in but do not have information from database -How i will knwo this?
      else if(user && user!=null 
              && user.wwid!=null && user.wwid.trim().length>0
              && (user.role==null || user.role=='undefined') ){
        this.router.navigate(['welcome']);
        return false;
      }else{
        // redirect user to oidc urls
        this.router.navigate(['welcome']);
        return false;
      }
    })
    return false;
  }

Expected: Return current user info Actual: Returns null

2
this.document.location.href = environment.callbackUrl; I think this line is reloading the application from the ground up. Are you sure you are not experiencing a full reload? when navigating from one page to the other in Angular, you should use the Angular router.A. Chiesa
Where are you calling setUserInfo(user)?Daniel Habenicht
Please share more of your code or describe the full context. It is obvious that you retrieve null since the canActivate guard is called even before user details get added. You need to triage what calls it (Page load?)Sergey Rudenko
Sorry, the canActivate method, as your definition says, should return boolean, not UserInfoMiguelSsSRrR
@A.Chiesa, the callbackUrl is to all the IDP and the login component sets the user info after that call. So I think there is no reload happening therescu

2 Answers

1
votes

I would say that the root of your problem in your canActivate method, is that at the moment is called, you still don´t have the information of the user, and as you have initialized the BehaviorSubject with null value, this is exactly what you get there.

Instead of returning the value, I would return the the userSubject as an Observable, and subscribe to it on your canActivate method:

userSubject: BehaviorSubject<UserInfo> = new BehaviorSubject<UserInfo>(null);
 setUserInfo(user: UserInfo){
    if(user && user !=null){
      this.userSubject.next(user);
    }
  }
 getUser() {
    return this.userSubject.asObservable();
  }

And the guard:

 canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {

    let userInfo:UserInfo;  
    this.authService.getUser().subscribe(user => userInfo = user);
    return true;
}

Hope that helps you!

;)

0
votes

Thanks everyone. All the comments were helpful and my issue was the auth service was getting initialized in my nav component. And that's the reason it always had null value. This answer helped me think in that direction: Cannot pass data with service in angular2