Mastering the Correct Usage of AuthGuard

I am facing an issue with implementing authguard in my angular application. I have set up a post request to my spring boot backend, and upon success, I set a value to true which I then check in my canActivate method of the authguard. However, for some reason it does not seem to be working as expected. I thought that by setting canActivate in my path within app-route.module, it would automatically be triggered. How can I correct this implementation?

Here is how I have set up the AuthenticationService along with AuthGuard:

export class AuthenticationService {

  constructor(
    private http: HttpClient,
    private router: Router,

  ) { }

  authenticateUser(login: LoginModel){
    return this.http.post(environment.rootUrl + 'authenticate', {
      username: login.username,
      password: login.password,
    }).subscribe({
      next: (data) => {
       localStorage.setItem('token', data.toString())
      }, error: (error) => {
        this.isAuthenticated = false
      }
    })
  }

  isUserLoggedIn(){
    return !!localStorage.getItem('token')
  }
}

And here is the implementation of AuthGuard:

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

  constructor(
    private auth: AuthenticationService,
    private router: Router
  ) {
  }

  canActivate(): Promise<boolean> {
    return new Promise(resolve => {
      if (this.auth.isUserLoggedIn()) {
        resolve(true)
      } else {
        this.router.navigate(['authenticate'])
        resolve(false)
      }
    })
  }
}

Additionally, here is how I have configured AppModule:

@NgModule({
  declarations: [AppComponent, NxWelcomeComponent],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    NbLayoutModule,
    LoginComponentModule,
    AppRoutingModule,
    NbThemeModule.forRoot({ name: 'default' }),
    NbLayoutModule,
    NbEvaIconsModule,
  ],
  providers: [AuthGuard],
  bootstrap: [AppComponent],
})
export class AppModule {}

And finally, the configuration in AppRoutingModule:

const routes: Routes = [
  {path: 'dashboard' , component: DashboardComponent, canActivate: [AuthGuard]},
  {path: 'authenticate', component: LoginComponent},
  {path: '' , redirectTo: 'authenticate', pathMatch: 'full'}
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [AuthGuard]
})
export class AppRoutingModule {}

Answer №1

If you want to access the dashboard post successfully logging in, you must set up appropriate routing:

The specified routes are as follows:

const routes: Routes = [
  {
    path: 'dashboard',
    component: DashboardComponent,
    canActivate: [AuthGuard],
  },
  { path: '', redirectTo: 'authenticate', pathMatch: 'full' },
];

The Component configuration is as per below:

export class AppComponent {
  constructor(
    private authService: AuthenticationService,
    private router: Router
  ) {}

  callServiceMethod(value: string) {
    // Wait for authentication before navigating within the app.
    this.authService.authenticateUser(value);
    if (this.authService.isAuthenticated) {
      this.router.navigate(['dashboard']);
    }
  }
}

Furthermore, an AuthGuard has been implemented:

@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
  constructor(private auth: AuthenticationService, private router: Router) {}

  canActivate(): Promise<boolean> {
    return new Promise((resolve) => {
      console.log('auth guard execution in progress!');
      if (this.auth.isUserLoggedIn()) {
        resolve(true);
      } else {
        this.router.navigate(['authenticate']);
        resolve(false);
      }
    });
  }
}

To view an updated example, click on the following link:

https://stackblitz.com/edit/angular-ivy-5excpc?file=src%2Fapp%2Fapp.component.ts

Answer №2

Ensure that your canActivate function is configured to accept only the AuthGuard class which includes the resolver.

{path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard]}

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

Troubleshooting Error 405 in AJAX, Javascript, Node.js (including Body-Parser and CORS), and XMLHttpRequest

I have been working on creating a JSON file from buttons. While I am able to retrieve data from the JSON files that I created, I am facing issues with posting to them using XMLHttpRequest and Ajax. Interestingly, I can add to a JSON file using routes just ...

What changes occurred to module file names following the process of minification?

I'm currently troubleshooting an issue with this particular code snippet: import globalComponents from './global-components'; // ... globalComponents.forEach((component) => { // eslint-disable-next-line no-underscore-da ...

summing up the initial elements from every array generated dynamically

My data is structured as follows: { "questions": ["Variety of food options", "Food quality", "Freshness of food"], "countries": ["Netherlands", "Belgium", "France"], "values": [ [ [5, 88, 18], [50, 83, 10], ...

What is the reason for the addEventListener function not being able to access global variables?

I have set up an event listener function to utilize popcorn.js for displaying subtitles. Additionally, I have created functions that are unrelated to popcorn.js outside of the event listener and declared a global variable array. However, when attempting ...

Having trouble getting all buttons to update at once? When using JavaScript and AJAX, only the first button seems to get updated

I have successfully developed my own custom "like" button feature. Utilizing AJAX, I can seamlessly update the database to increment the "like" count by 1. Subsequently, JavaScript handles the task of updating the first "like" button with the revised infor ...

Exploring the use of v-model in Vue3 child components

After some exploration, I recently discovered that in Vue3, the v-model functionality does not work responsively or reactively with child Component. The following code snippet showcases how the username data gets updated: <template> <div> ...

The positioning of drawings on canvas is not centered

I'm facing an issue while attempting to center a bar within a canvas. Despite expecting it to be perfectly centered horizontally, it seems to be slightly off to the left. What could possibly be causing this discrepancy? CSS: #my-canvas { border: ...

Encountered a MongoDB error: $pushAll modifier is unrecognized when trying to update a model using Mongoid, Angular, and Rails frameworks

My stack includes angular-8 on the front-end and Rails(5.2) on backend with Mongoid(6.1). I'm working with a multi-level nested form for my Event model, which utilizes accepts_nested_attributes_for for Ticket that in turn accepts_nested_attributes_fo ...

Development of Chrome Extensions, JavaScript dilemma

Hey there, I'm new to JavaScript and I've been diving into the world of creating Chrome extensions. I'm trying to set up a content script and browser action, but I'm struggling to get it up and running. I know I'm probably making a ...

Accessing information from an Angular Elements Web Component using vanilla JavaScript

I am in the process of creating several WebComponents that I plan to utilize across various libraries and frameworks, with a primary focus on plain vanilla JavaScript. My current consideration is to implement Angular Elements for this purpose, and I have a ...

What is the best way to transfer information to the canActivate service guard?

Here is the route definition: { path:'specific_path', component: specific_component, canActivate: specific_service} What is the best way to send data to the specific_service? ...

Prevent the Icon in Material UI from simultaneously changing

I'm working on a table where clicking one icon changes all icons in the list to a different icon. However, I want to prevent them from changing simultaneously. Any suggestions on how to tackle this issue? Code: import React from 'react'; im ...

Is it necessary to generate a file for each API in Next.js?

When working with Next.js, it is common practice to create a separate file for each new API endpoint. For example, for the /user endpoint, there would be a user.js file with its own handler, and another one for /user/goldmember. Some may argue that this ...

Listen for the load event during an AJAX request without using jQuery's add

I have four HTML files and four corresponding JavaScript files. Each JavaScript file is externally loaded by its respective HTML file. Specifically, index.html loads javascript.js, 1.html loads javascript1.js, 2.html loads javascript2.js, and 3.html loads ...

Creating a Related Entry in strapi v4: A Step-by-Step Guide

Whenever I try to add a new record in my Collection-Type, all the field values are successfully added to the new entry except for the value in the field with a Relation type. For instance, in my event Collection-Type, I have fields like name, performers, ...

Issues with Internet Explorer's scaling functionality are preventing it from operating correctly

I've utilized d3 to create a map. Its width is dynamically set based on the parent div's (with the id "map") width, and its height is calculated with a ratio of 5/9 in relation to the width. The viewBox attribute has been defined as "0 0 width he ...

Secure HyperText Transfer Protocol prevents JavaScript from executing

My website's HTTPS version is having trouble loading JavaScript. All scripts are hosted on the same server. I've attempted: <script type="text/javascript" src="https://server.tld/js/jquery.js"> <script type="text/javascript" src="//ser ...

Send the form data from a modal controller in AngularJS to an ng-controller outside of the modal

There seems to be a confusion with the functionality not working as expected: In my Angular application, I have a main page with an ng-controller named "SearchCtrl" that handles sending search requests to a webserver. app.controller('SearchCtrl&apos ...

In Typescript, what sets apart a generic written before a function compared to after a type declaration?

Can you explain the difference between these two type declarations for arrow functions? export type Sort = <D>(r: Rows<D>, f: Field<D>, o: Order) => Rows<D>; export type Sort<D> = (r: Rows<D>, f: Field<D>, o: ...

Is there a way to trim an image in react js once it has been uploaded?

Is there a way to crop an image in react js after uploading? Hello everyone! I need to crop or edit an image after uploading it, but I'm not sure how to do it. I want to maintain a constant aspect ratio while cropping. I attempted to use react-easy-c ...