angularopenid-connectoidc-client-jsoidc-client

this.user is undefined when fetch data from app.component in angular -oidc-client


I am using oidc-client.js in my angular project.

Right now users could log-in and log out and it works fine. the only problem is that when I want to call a service in app.component, in the interceptor the user is not authenticated.

auth.service is :

    Injectable({
  providedIn: 'root'
})
export class AuthService extends BaseService {


  private _authNavStatusSource = new BehaviorSubject<boolean>(false);

  authNavStatus$ = this._authNavStatusSource.asObservable();

  private manager = new UserManager(getClientSettings());
  private user: User | null;


  constructor(private http: HttpClient) {
    super();   
    this.manager.getUser().then(user => {
      this.user = user;
      this._authNavStatusSource.next(this.isAuthenticated());
    });
  }

  login() {
    return this.manager.signinRedirect();
  }

  async completeAuthentication() {
    this.user = await this.manager.signinRedirectCallback();
    this._authNavStatusSource.next(this.isAuthenticated());
  }


  isAuthenticated(): boolean {
    return this.user != null && !this.user.expired;
  }

  get authorizationHeaderValue(): string {
    return `${this.user.token_type} ${this.user.access_token}`;
  }

  async signout() {
    await this.manager.signoutRedirect();
  }
}

export function getClientSettings(): UserManagerSettings {
  return {
    authority:environment.authApiURI,
    client_id: 'medilloxdashboard',
    redirect_uri: environment.redirect_uri,
    post_logout_redirect_uri: environment.postLogoutRedirectUri,
    response_type: "id_token token",
    scope: "openid spa profile",
    filterProtocolClaims: true,
    loadUserInfo: true,
    automaticSilentRenew: true,
    silent_redirect_uri:environment.silentRedirectUri,
    userStore: new WebStorageStateStore({ store: localStorage })
  };
}

and I wrote an interceptor to add token to all requests like this :

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  private authorizationHeader = "Authorization";

  constructor(
    private authService: AuthService,
    private router: Router) { }
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    request = request.clone({
      headers: request.headers.set(this.authorizationHeader, this.authService.authorizationHeaderValue)
    });
    return next.handle(request);
  }

}

AuthService and AuthInterceptor are registered in Core nodule.

In the App.Compoentn I call a service like this which call a REST api

    export class AppComponent implements OnInit {

  title = 'myapp';
  version: string;

     constructor(
        private router: Router,
        private dashboardService: DashboardService) {
        this.version = environment.version;
      }
    
      ngOnInit(): void {
        this.dashboardService.getDashboards().subscribe();
      }
    }

when this call happen, I get getDashboards failed: this.user is undefined but I call exactly this service in another components and it works fine.

components which call this service and get the result are in their modules.

Where is the problem?


Solution

  • I created an Initializer like this

    import { AuthService } from "./auth-service";
    export function AuthInitializer(auth: AuthService) { return () => auth.isAuthenticated() };
    

    and registered like this in core.module

    providers: [
    
    {
      provide: APP_INITIALIZER,
      useFactory: AuthInitializer,
      deps: [AuthService],
      multi: true
    }]
    

    this is working perefectly.