2

I am building an application using Angular 7, I have handled the API calls, the JWT Token authentication system using C#, and also updating the LocalStorage() when necessary, when the user logs in and logs out, and all these are working perfectly.

My problem is I want it to run a login check as a middleware within the application rather than on the lifecycle method - ng.onInit(). How do I go about this?

Is there a way to execute lifecycle events as an entry component or service. That is, before any component loads it is able to check if the user is logged in or not and redirect via Router to a desired page.

halfer
  • 19,824
  • 17
  • 99
  • 186
Ande Caleb
  • 1,163
  • 1
  • 14
  • 35
  • If you do a singleton, only one instance of the service will exist in the app. Maybe that will help? https://angular.io/guide/singleton-services – Nick Gallimore Jan 21 '20 at 14:25
  • Use `APP_INITIALIZER`. https://stackoverflow.com/questions/49707830/angular-how-to-correctly-implement-app-initializer – mbojko Jan 21 '20 at 14:26
  • You can try Can Activate interface to make it as same as middleware https://angular.io/api/router/CanActivate – carte Jan 21 '20 at 14:27
  • You can handle the login check in the app.component.ts, you simply inject the service there. Then you set that value in the local storage. Then you can use a custom Guard to restrict access to pages. Also, set a bool in the service to true if they are logged in. Then you inject that auth service in other components and you check that value. Only set the value in the app.component.ts though. – Nick Gallimore Jan 21 '20 at 14:27

3 Answers3

5

Guard is based on the routes... so I think you should prefer a module/service solution.

import { APP_INITIALIZER } from '@angular/core';

then add it as a provider like this :

 export function initApp(initService: YourInitService) {
  return () => { 
    initService.Init();
  }
}
    { provide: APP_INITIALIZER,useFactory: initApp, deps: [YourInitService], multi: true } 
  • 1
    Hint: You can also return a Promise for the APP_INITIALIZER. (return initService.init()) to wait until the loading is completed. (Display a loading indicator for UX. It's better than a black screen.) – Domske Sep 22 '20 at 10:01
1

You should check for Guard in angular, especially canActivate Guard: https://angular.io/guide/router

A guard is created like this:

@Injectable({
  providedIn: 'root'
})
export class MyGuard implements CanLoad {
 constructor() {}

 canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> | 
 Promise<boolean> | boolean {
   const x = true;
   if (x) {
     return true; // It allows access to the route;
   } else {
      // redirect where you want;
     return false; // it doesnt allow to access to the route
  }
 }
}

Then in your routing Module:

{
path: "yourRoute",
canActivate: [MyGuard],
component: YourComponent
}

For authentication, you have a good library that uses guard here: https://www.npmjs.com/package/ngx-auth

Soukyone
  • 568
  • 2
  • 13
  • ello please can you check your code again, at the line where it says `Observable | Promiseboolean` i'm getting an error here that 'boolean' only refers to a type, but is being used as a value here, please help look into it. – Ande Caleb Jan 21 '20 at 14:58
  • Yes, i am sorry, it was a typing mistake, the function canActivate can return boolean, or promise or observable (I edited) – Soukyone Jan 21 '20 at 15:02
  • how do i load the myGuard on the app.module.ts as an `entrycomponent` or `the providers array` or in `the declarations array`, or should i omit it.? – Ande Caleb Jan 21 '20 at 15:08
  • As a provider normally, but if you used the @Injectable([ providedIn: 'root'}) annotation, on the guard, you dont need to add it to providers: []. It will provide it automatically on the root scope. – Soukyone Jan 21 '20 at 15:14
  • ok, thanks, it works by restricting the pages as expected when a user is logged out, but when you eventually log in, it throws an `Invalid CanActivate guard Error: Invalid CanActivate guard` – Ande Caleb Jan 21 '20 at 15:29
  • Care to correctly return true, in your guard, if the user is logged in. Your canActivate function has to return something in all case. – Soukyone Jan 21 '20 at 15:34
0

You should implement an authGuardService or something like that to use as middleware for your routing (using the canActivate section)

See: https://angular.io/api/router/CanActivate

This prevents routes from being loaded if the canActivate fails the condition (which is preferred when using a login system etc instead of checking in lifecycle hooks).

Bert Maurau
  • 979
  • 5
  • 21