How can I resolve the infinite loop issue caused by Angular Auth guard when using routing?

My current struggle lies within the authentication guard logic and routing setup.

In my app-routing.module.ts file, I have defined 3 routes:

const routes: Routes = [
  {
    path: '',
    loadChildren: () => import('./browse/browse.module').then(m => m.BrowseModule),
  },
  {
    path: AppRoutes.auth,
    loadChildren: () => import('./auth/auth.module').then(m => m.AuthModule)
  },
  {
    path: AppRoutes.landing,
    loadChildren: () => import('./landing/landing.module').then(m => m.LandingModule),
  },
];

One of these paths leads to the '' route which sends users to the BrowseModule at /browser.

Within the browser-routing.module.ts, I've implemented an AuthGuard that redirects users to the landing page if they are not authenticated:

const routes: Routes = [
  {
    path: '',
    component: BrowseComponent,
    redirectTo: BrowseRoutes.browse,
  },
  {
    path: BrowseRoutes.browse,
    loadChildren: () => import('./home/home.module').then(m => m.HomeModule),
    canActivate: [AuthGuard]
  }
];

AuthGuard.ts :

  canActivate(
    route: ActivatedRouteSnapshot
  ): Observable<boolean> | Promise<boolean> | boolean {
    if (this.authService.hasToken()) {
        if(this.authService.isAuthenticated()){
          console.log('logged in guard');
          this.router.navigate(['browse']);
            return true;
        } else {
          console.log('not logged in guard');
            this.router.navigate(['landing']);
            return false;
        }
    } else {
      console.log('no token not logged in guard');
      this.router.navigate(['landing']);
      return false;
    }


  }

The issue at hand is :

When I am logged in, there seems to be an infinite loop occurring with the AuthGuard. It continuously prints either "not logged in" and cycles between "/" and "/browse", or it shows "logged in" and enters an infinite loop once more. How can this be resolved?

Answer №1

When the condition is met, there is no need to navigate away from the guard. By doing so, the guard takes control of a decision it shouldn't be responsible for, limiting its reusability for other paths as it will always redirect to /browse. The guard's role is to validate and should only navigate when a condition is not satisfied.
Your canActivate method should follow this structure:

if (isLoggedIn()) {
  return true;
}
this.router.navigate(['landing']);
return false;

Answer №2

Optimizing Angular Routing Referencing the official Angular documentation on routing at "https://angular.io/guide/router"

The order in which routes are configured plays a crucial role due to the first-match wins strategy employed by the router. This means that more specific routes should be prioritized over less specific ones. In the provided configuration, routes with static paths are listed before an empty path route, which serves as the default route. The wildcard route is placed last as it acts as a fallback only when no other routes match.

It appears that your current route consistently matches the first route 'browser.module', following Angular's 'first-match wins' principle.

To optimize this, consider rearranging your routes as shown below:

const routes: Routes = [

  {
    path: AppRoutes.auth,
    loadChildren: () => import('./auth/auth.module').then(m => m.AuthModule)
  },
  {
    path: AppRoutes.landing,
    loadChildren: () => import('./landing/landing.module').then(m => m.LandingModule),
  },
  {
    path: '',
    loadChildren: () => import('./browse/browse.module').then(m => m.BrowseModule),
  },
];

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the reasoning behind ethers.js choosing to have the return value of a function be an array that contains the value, rather than just the value itself

An issue arose with the test case below: it('should access MAX_COUNT', async () => { const maxCount = await myContract.functions.MAX_COUNT(); expect(maxCount).to.equal(64); }); The test failed with this error message: ...

Creating a generic that generates an object with a string and type

Is there a way to ensure that MinObj functions correctly in creating objects with the structure { 'name': string }? type MinObj<Key extends string, Type> = { [a: Key]: Type } type x = MinObj<'name', string> Link to Playgr ...

The Angular material checkbox has a mind of its own, deciding to uncheck

I am having an issue with a list displayed as checkboxes using angular-material (Angular 7). Below, I will provide the code snippets for both the .html and .ts files. Every time I click on a checkbox, it gets checked but then immediately becomes unchecked ...

When a user clicks on the download link, it redirects them to the homepage in Angular

When using Angular 6 and the downloadFile method to download an Excel sheet from the WebAPI, everything runs smoothly. A dialog box opens up asking to save the file on the drive, but then it unexpectedly navigates me back to the home page. This redirects ...

Having issues with Angular 2/4 unable to read an object within the initForm() function

In the process of creating an edit form using Angular, I am facing a problem with understanding the lifecycle of the object retrieved from my backend server. After making a call to my service in ngOnInit(), I receive valid data. However, when I assign this ...

Examining Angular tests for window.location.href changes

authenticate() { const url = environment.authenticationEndpoint; window.location.href = url + '/login'; } I have an Angular service file containing the above code which redirects to the login URL. In order to unit test this, I added the foll ...

Angular 8 - Customizing primeng/fullcalendar Appearance Based on Event Type (Looping Events) and Cell Background Color

This is how I have integrated fullcalendar into my Angular 8 application: calendar.component.ts: export class MyCalendarComponent implements OnInit { public plantedActivities: PlantedActivityModel[] public actuatorActivities: ActuatorActivityModel ...

Storing a reference globally in React and Typescript: Best practices

In my application, I have multiple instances of a specific component called <Item>. Each <Item> needs to display a dynamic tooltip when hovered over. To achieve this, I am utilizing semantic-ui-react and its Popup component. The conventional m ...

What is the best way to incorporate or reference an existing AngularJS project in a new project?

https://i.stack.imgur.com/2dkC0.png The image suggests that Angular app1 serves as a shared module for both app2 and app3. Is there a way to inject app2 and app3 into the common module? If direct injection is not possible, does anyone have suggestions on ...

Typescript objects may contain keys that are dependent on certain parameters

I have a challenge with constructing an object that requires querying multiple database tables, resulting in a time-consuming process. To address this issue, clients of the object need to specify which specific parts they require. For example, let's c ...

Utilizing ngClassEven and ngClassOdd in Angular 2 for Improved Styling

I attempted to replicate the behavior of ng-class-even and ng-class-odd (originally from Angular 1) in my Angular 2 application. Below is the code I wrote and it's functioning correctly, but I'm curious if there are alternative methods to achiev ...

Angular's queryParams do not appear to properly connect with the query parameters

My code seems to have a mistake somewhere, but I can't figure it out. In my [queryParams] = "{allowEdit: server.id == 3 ? 1 : 0}", the params object is empty when I subscribe to it in the edit-server component. Why is it empty and how do I a ...

How can we recreate this ngModel text input form in a radio format for a spring boot mvc and angular application?

As I was following a tutorial on creating an employee CRUD model using spring boot and mysql server for the backend and angular for the frontend, I encountered a form group during the creation process. The tutorial originally had a text input field for gen ...

When using Validators.pattern('^[0-9][0-9][0-9]$') in Angular 9, it does not validate numbers with a leading 0, such as 012

When attempting to validate a simple PIN with the possibility of leading zeros, I created this basic regular expression: ^[0-9][0-9][0-9][0-9][0-9][0-9]$ Although this regex worked fine on various online tools for testing regular expressions, it failed i ...

TS2392 error: Implementing multiple constructors in Angular 2 is not permitted

Is there a more efficient way to avoid using multiple constructors in a component? Currently, I am encountering the following error: 'Multiple constructor implementations are not allowed'. questions: any[]; constructor( service: QuestionSignup ...

Validator checking the status of an Angular form

Currently working on developing a custom form validator. In my test component, there are three checkboxes. The main form should only be considered valid if at least one checkbox is checked. https://stackblitz.com/edit/stackblitz-starters-69q3rq Within th ...

How to handle multiple formData input in NestJS controller

How can I create a controller in Nest.js that accepts two form-data inputs? Here is my Angular service code: public importSchema(file: File, importConfig: PreviewImportConfig): Observable<HttpEvent<SchemaParseResponse>> { const formData = ...

Tips for applying personalized CSS to individual Toast notifications in Angular

MY QUESTION : I am looking to customize the CSS of a single toast used in Angular components. While there may be multiple toasts, I specifically want to style one particular toast differently. For example, the toast image can be viewed here: example toast ...

Can you explain the distinction between any[] and [] in TypeScript?

Here is an example that successfully works: protected createGroups(sortedItems: Array<TbpeItem>): any[] { let groups: any[] = []; return groups; } However, the second example encounters a TypeScript error: type any[] not assignable to ...

Storing a portion of JSON data within a function called in the HTML document

I've been working with Angular and need to save a portion of JSON data in a variable within a function that is called in an HTML file: <select id="postazione" onchange="postazioneSelezionata()"> <option value="" selected disabled >Cho ...