1

promise from oidc-client in angular 10 constructor is taking too long to resolve, the isLoggedIn function is being called before the constructor places de value in the user variable.

this is my code:

import { UserManager, UserManagerSettings, User } from 'oidc-client';

export class AuthService {
  private user: User = null;
  private manager = new UserManager(getClientSettings());
  privatecachedRequests: Array<HttpRequest<any>> = [];

  constructor() {
    this.manager.getUser().then(user => {
      this.user = user;
    });
  }
  isLoggedIn(): boolean {
    return this.user != null && !this.user.expired; <= this.user is null because the constructor did not finished the async part
  }

this code was working in angular 8

when I called getUser() function inside my isLoggedIn method, it worked, but i would like to use this from the constructor

GiovaniHarada
  • 35
  • 1
  • 8
  • 1
    where and how are you consuming `isLogged()` method? – Vikas Aug 17 '20 at 05:13
  • 2
    AFAIK the issue is not related to Angular Version, Async execution needs to be handled appropriately, if you could provide some insight I would be able to give you the solution. – Vikas Aug 17 '20 at 05:20
  • i'm using the isLogged() inside my route guard (canActivate) canActivate(): boolean { if (this.authService.isLoggedIn()) { return true; } this.authService.startAuthentication(); return false; } – GiovaniHarada Aug 17 '20 at 05:23
  • Ahan that would be enough ,Give me a moment. – Vikas Aug 17 '20 at 05:24
  • 1
    Consider using an `APP_INITIALIZER` to configure perform the asynchronous initialization of the service. – Aluan Haddad Aug 17 '20 at 09:49
  • thank you @AluanHaddad, i will search for your sugestion – GiovaniHarada Aug 27 '20 at 23:47

1 Answers1

1

Use Rxjs Subject to act as a proxy.

import {Subject } from 'rxjs',<-- add this
export class AuthService {
  private user: User = null;
  private manager = new UserManager(getClientSettings());
  privatecachedRequests: Array<HttpRequest<any>> = [];
  private loginSubject= new Subject()<-- add this line

  constructor() {
    this.manager.getUser().then(user => {
      this.user = user;
      if(this.user != null && !this.user.expired)
       {
         this.loginSubject.next(true)
       } else{
           this.loginSubject.next(false)
          }
     
    });
  }
  isLoggedIn(): Observable<boolean> {
     return this.loginSubject.asObservbale();<-- avoid leak 
  }

you can return Observable in canActivate

import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import {map} from 'rxjs/operators';


@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private authService:AuthService, private router: Router) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>  {
    return this.authService.isLoggedIn().pipe(
      map(res => {
        if (res) {
          return true;
        } else {
          this.router.navigate(['/login']);
           return false
        }
      })
  }   

}
Vikas
  • 10,066
  • 7
  • 34
  • 58