osman Rahimi
osman Rahimi

Reputation: 1507

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?

Upvotes: 1

Views: 896

Answers (3)

osman Rahimi
osman Rahimi

Reputation: 1507

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.

Upvotes: 0

Nadhir Houari
Nadhir Houari

Reputation: 410

To answer to your question @osman Rahimi "In ngAfterViewChecked it is ok but this code run whenever I click on each butttons. Is there a better way?"

The answer :

  data: any;
  ngAfterViewChecked (): void {
    if(this.data === null || this.data === undefined) {
      this.dashboardService.getDashboards().subscribe(data => this.data = data);
    }
  }

Upvotes: 1

Nadhir Houari
Nadhir Houari

Reputation: 410

Try to make your call inside and ngAfterViewCheck instead of ngOnInit because services at this moment aren't initiated yet. Be careful that would be executed infinitely. You can keep make the call, while the user is undefined.

Upvotes: 1

Related Questions