0
votes

I am pretty new to Angular and I'm trying to write a auth guard in my application, I know I can hit my server everytime and get session info about the user that is logged in. But I'd like to like keep track of the logged in user throughout the application...

app.component.ts

  export class AppComponent implements OnInit {
  title = 'APPTITLE';
  logged_in = true;

  constructor(private authService: AuthenticationService){}
  ngOnInit(){
    this.authService.isAuthenticated.take(1)
    .subscribe(res => {
      console.log(res);
      this.logged_in = res});
  }
}

AuthenticationService.ts

@Injectable()
export class AuthenticationService {    
    private currentUserSubject = new BehaviorSubject<IUser>(<IUser>{});
    public currentUser = this.currentUserSubject.asObservable().distinctUntilChanged();
    private isAuthenticatedSubject = new ReplaySubject<boolean>(1);
    public isAuthenticated = this.isAuthenticatedSubject.asObservable();
    private isAdminSubject = new ReplaySubject<boolean>(1);
    public isAdmin = this.isAdminSubject.asObservable();

    constructor(private http: HttpService) {
        this.isAuthenticatedSubject.next(false);
        this.isAdminSubject.next(false);
    }

    login(username: string, password: string, onSuccess: (data) => void, onError: (data) => void=null): any {
        this.isAuthenticatedSubject.next(true);
        let query_url = 'login';
        let payload = JSON.stringify({username: username, password: password});
        return this.http.post(query_url, payload)
        .subscribe(user => {
            this.currentUserSubject.next(user);
            this.isAuthenticatedSubject.next(true);
            if (user.usertype == 'admin') this.isAdminSubject.next(true);
            onSuccess(user);
        },
        error => {
            if (onError){
                onError(error);
            }
        });
    }

    logout() {
        let query_url = 'logout';
        return this.http.post(query_url, null)
        .subscribe(res => {
            this.currentUserSubject.next(null);
            this.isAuthenticatedSubject.next(false);
            this.isAdminSubject.next(false);
        })
    }
}

auth-guard.ts

@Injectable()
export class AuthGuardService implements CanActivate {

  constructor(private router: Router, private authService: AuthenticationService) {

  }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>{
    return this.authService.isAuthenticated.take(1)
  }
}

login.component.ts

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css'],
  providers: [AuthenticationService]
})

export class LoginComponent implements OnInit {
    error_message: string = 'Login Unsuccessful'
  login_info: any = {};

  constructor(public router: Router, 
    private authenticationService: AuthenticationService) {

  }

  ngOnInit() {
  }

  formSubmitted(data): void {
    this.login(data.username, data.password);
  }


  login(username, password) {
    event.preventDefault();
    this.authenticationService.login(username, password, (data) => {
      console.log(data);
    },
    (err) => {
      console.log(err);
    })
}

auth-guard will always return false here, I'm not sure why. Are the authentication services defined in auth-guard and login different entities?

2
How many times did you initialize the service in the app. I mean add in a provider . Also remove take(1)Vamshi

2 Answers

0
votes
return this.authService.isAuthenticated.take(1)

Always returns the first value.

Documentation for take : Returns a specified number of contiguous elements from the start of an observable sequence

Change it to

return this.authService.isAuthenticated;
0
votes

It s probably because you created the observable from an empty (or just initialized) subject. Observable are taking the value into the subject one time, when you instanciate it. If you want to use it as an Observable, instanciate it in a method or a getter.

get isAuthenticated ()  { return this.isAuthenticatedSubject.asObservable(); }