Angular Auth Guard with a Promise and if statement

Viewed 1247

I want to use a guard to decide whether or not a user can navigate to the login pag, but I know my logic is faulty because of a Promise. See my code below.

  canActivate(): boolean | Observable<boolean> | Promise<boolean> {
    if (!this.localStorage.getObject('isInitialized')) {
      this.router.navigate(['/locaties']);
      return true;
    }
    return false;
  }

I know what I'm doing is wrong, but I'm lacking the knowledge about promises to go around this. What do I need to do to make this work?

This is my localstorage.getObject():

  // Returns object
  async getObject(key: string) {
    const ret = await Storage.get({ key: key });
    return JSON.parse(ret.value);
  }
3 Answers

If you want to use an async result based condition in your can activate method then you can use Promise. If you intend to use a direct value from the local storage then you need not use promise. You can do something like below to use promise...

canActivate(): Promise<boolean> {
  return new Promise((resolve) => {
    if (!this.localStorage.getObject('isInitialized')) {
      this.router.navigate(['/locaties']);
      // Do not allow the route
      resolve(false);
    } else {
      // Allow the route
      resolve(true);
    }
  });
}

So there a couple things wrong here but I don't think the promise is one of them. Your function signature says that you have the option to return one of three types,

canActivate(): boolean | Observable<boolean> | Promise<boolean>

But you only ever return a boolean, so really you could re-write this as just,

canActivate(): boolean

But that isn't the issue. It is hard to say without seeing your route setup, but it looks like you are re-routing the user if the route they are requesting is allowed and that isn't necessary. Route guards run when the user is already trying to navigate to a page. If the route guard returns true, that navigation is allowed to happen and the user will proceed to whatever page the route guard is protecting.

But you should be specifying the re-direct page when the route guard returns false. In other words, when the user cannot access the page behind the guard, where do you want to send them?

In general, that would look something like this,

@Injectable()
export class AuthGuard implements CanActivate {
    constructor(private router: Router) {}

    canActivate(state: RouterStateSnapshot): boolean {
        if (!this.localStorage.getObject('isInitialized')) {
            //No need to route here, user will be taken to the route they were trying access
            return true;
        } else {
            //Send the user back to the '/anotherpage' path if they are not logged in
            this.router.navigate(['/anotherpage']);
            return false;
        }
    }
}

Then define your routes somewhere like this,

export const appRoutes: Routes = [
    {
        path: 'pageProtectedByAuthGuard',
        component: YourComponent,
        canActivate: [AuthGuard]
    }
];

Then in your module you need to import those routes,

@NgModule({
    imports: [RouterModule.forRoot(appRoutes, { enableTracing: false })],
    ...
})

More on CanActivate here: https://angular.io/api/router/CanActivate

The answer was

    this.localStorage.getObject('isInitialized').then((res) => {
      if (res == true) {
        this.router.navigate(['/locaties']);
        return false;
      }
    });
    return true;
  }

Got to remember the the auth guard gets triggered when the user wants to navigate to the page. No need to make it more complicated than that

Related