Authentication checkpoint within an Angular application using a JWT cookie

After searching extensively, I was unable to find a question that directly addresses my specific concern. Currently, I am working on a project involving an angular application that utilizes jwt and http-only cookies for authentication. In order to authenticate requests on the backend, the jwt cookie is sent with each request. While everything is functioning properly, I am curious about the most effective method for verifying user authentication - particularly the WHERE.

From my research, it seems that the common approach involves using AuthGuards and a custom AuthService to validate Authentication and secure routes. In my case, I can verify authentication by utilizing an endpoint /api/users/currentuser which is solely dedicated to checking the jwt token and responding with a user object if the user is authenticated. This method works well, but I am uncertain about the optimal location within an angular application to trigger this request.

  • Should I place the request in the constructor of my AuthService, ensuring it is the first operation executed and then set a BehaviorSubject<boolean> that other components can subscribe to?

     export class AuthService {
     isLoggedIn$ = new BehaviorSubject < boolean > (this.isLoggedIn);
     ...
     constructor() {
       // initiate call to /api/users/currentuser backend 
       // set isLoggedin$ to true/false based on currentuser response
       this.isLoggedIn$.next(value);
     }
    
  • Should the AuthGuard responsible for protecting one or more routes perform its own request to the backend within canActivate method?

     canActivate(
         route: ActivatedRouteSnapshot,
         state: RouterStateSnapshot
       ):
         | Observable<boolean | UrlTree>
         | Promise<boolean | UrlTree>
         | boolean
         | UrlTree {
         if (!this.authService.getCurrentUser()) {
           console.log('NOT authenticated');
           this.router.navigate(['']);
           return false;
         }
    
         console.log('AUTHENTICATED');
         return true;
       }
    
  • Or should the AuthGuard subscribe to the AuthService BehaviorSubject like this:

     canActivate(
         route: ActivatedRouteSnapshot,
         state: RouterStateSnapshot
       ):
         | Observable<boolean | UrlTree>
         | Promise<boolean | UrlTree>
         | boolean
         | UrlTree {
         if (!this.authService.isLoggedIn$.getValue()) {
           console.log('auth guard NOT authenticated');
           this.router.navigate(['']);
           return false;
         }
    
         console.log('AUTHENTICATED');
         return true;
       }
    
  • Should the call to /api/users/currentuser be executed using async ... await ... at the beginning of the page load to ensure authentication is verified before the page is rendered?

  • Particularly after a page refresh - where is the ideal location for the authentication process to occur?

Is there a definitive location within the application where a single call to /api/users/currentuser should occur? Should this call be made multiple times from various places (authservice, authguard, different components, etc) for security reasons or is there a more efficient approach to sharing the authentication status among components?

Current app.component.html:

<app-navbar></app-navbar>
<router-outlet></router-outlet>

Answer №1

Most individuals prioritize authentication as the first step in using an app. To achieve this, it is recommended to integrate authentication within a "preload" service.

You can create a service like this:

@Injectable({
    providedIn: 'root',
})
export class PreloadService {
    constructor(
        private authService: AuthService
        // add any other necessary imports
    ) {}

    public async initializeApp() {
        if (!this.authService.isLoggedIn()) {
            await this.authService.login() // or any other required action
        }     
    }
}

export function PreloadFactory(preloadService: PreloadService) {
    return () => preloadService.initializeApp();
}

Next, in the app.module:

    providers: [
        {
            provide: APP_INITIALIZER,
            useFactory: PreloadFactory,
            deps: [PreloadService],
            multi: true,
        },
    ]

By implementing this preload service, you can ensure that the user is authenticated during the App initialization process, before any routes are loaded.

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

Picture fails to load on Ionic app on the device

Currently, I am utilizing Ionic 3 for my project. The location of the images file is \src\assets\img. This pertains to a basic page implementation. export class BasicPage { items = []; constructor(public nav: NavController ,private adm ...

Tips for creating a draggable Angular Material dialog

Has anyone been able to successfully implement draggable functionality in an Angular Material Dialog? I've spent a considerable amount of time searching for a definitive answer but have come up empty-handed. Any insights or guidance would be greatly a ...

akka-http integrated with angular2 routing

Currently, I am facing an issue with serving my Angular2(rc3) app from akka-http (a Scala rest framework). The problem lies in routing. Whenever a request is made, spray attempts to locate /my/endpoint/declared/in/angular as a regular resource. How can I r ...

Is it possible to utilize AngularfireList without observables? In other words, can I retrieve an AngularfireList object directly from Firebase and then process it in

I am attempting to retrieve an object from Firebase using AngularFire and angularfirelist. However, the returned object is not what I expected. Here is my code: export class AdminProductsComponent implements OnInit { products$ : AngularFireList<unkn ...

Obtain a reference to a class using a method decorator

My goal is to implement the following syntax: @Controller('/user') class UserController { @Action('/') get() { } } Now in the definition of decorators: function Controller (options) { return function(target: any) { let id ...

The ultimate guide to loading multiple YAML files simultaneously in JavaScript

A Ruby script was created to split a large YAML file named travel.yaml, which includes a list of country keys and information, into individual files for each country. data = YAML.load(File.read('./src/constants/travel.yaml')) data.fetch('co ...

Issue with Angular 7: In a ReactiveForm, mat-select does not allow setting a default option without using ngModel

I have a Angular 7 app where I am implementing some reactive forms. The initialization of my reactive form looks like this: private initFormConfig() { return this.formBuilder.group({ modeTransfert: [''], modeChiffrement: [' ...

Customizing modal window HTML in ng-bootstrapNeed to override the default modal window

Currently, I am utilizing ng-bootstrap to create my modals. I have been pondering the most effective approach to customize the modal window's HTML. The default appearance of the modal html is somewhat like this: <div role="document" class="modal- ...

What is the best way to sift through slug data?

Struggling to display related posts from the same category in my project using Sanity for slug data. Attempted fetching all data and storing it in the state but unsure how to filter based on the current post's category. I'm thinking about leverag ...

My route seems to be malfunctioning, can someone please help me troubleshoot the

There seems to be an issue with my route in the app-routing.module.ts file because I encounter errors when I visit this page: However, everything works fine when I go here: import { NgModule } from '@angular/core'; import { Routes, Router ...

Transferring data between components in React by passing parameters through Links

When calling another component like <A x={y}/>, we can then access props.x inside component A. However, in the case of calling EditCertificate, the id needs to be passed to the component. I am using a Link here and struggling to pass the id successf ...

Using Checkbox from material-UI to add and remove strikethrough on a to-do list task

const Todo: React.FC<ITodoProps> = (props) => { const [textInput, setTextInput] = useState(''); const { addTodo, userId, todosForUser, user, } = props; if (user == null) { return ( <Grid container={true} direction=&apo ...

Ecommerce Template for Next.js

I am new to the world of web development and I have a project involving customizing a Next.js ecommerce template. Since I'm still learning programming, I would appreciate a simple summary of the steps I need to take in order to achieve this. The speci ...

Can we break down and explain iterative dynamic imports with conditions in JavaScript?

Is there a way to simplify the named imports and assignments in my code programmatically without repeating myself? I am looking for a solution that involves using a loop. This is what I currently have: import { globalLocale } from './i18n' let ...

Issues with implementing routing children in Angular 8

Currently, I am in the process of building a website and facing some issues with implementing the admin section. Within my admin module, I have various components such as login, dashboard, products, etc. However, I am encountering an issue where the childr ...

Don't forget to save the selected tab in Angular 5 using a bootstrap tabset

Using the tabset feature from Bootstrap (specifically ngx-bootstrap.es2015.js) in an Angular 5 application has been mostly successful. However, a common issue arises when navigating between components. When transitioning back to the component with the tabs ...

Ionic - What is the correct way to import ViewController? - Uncaught (in promise): Error: ViewController provider not found

I have a Popover in my app and I want it to behave differently based on the selected item. I followed the instructions in the Ionic documentation to achieve this. Error: Uncaught (in promise): Error: No provider for ViewController! When I tried adding ...

The issue here pertains to npm's inability to successfully retrieve a required dependency for download

C:\Users\Manoj\Desktop\accounts>npm install intro.js --save npm ERR! code ENOENT npm ERR! syscall spawn git npm ERR! path git npm ERR! errno ENOENT npm ERR! enoent Error while executing: npm ERR! enoent undefined ls-remote -h -t ssh: ...

What role do the esm directories serve within Angular 2 modules?

Currently, I am working with Angular2 RC4 and using the following packages: "@angular/common": "2.0.0-rc.4", "@angular/compiler": "2.0.0-rc.4", "@angular/core": "2.0.0-rc.4", "@angular/forms": "0.2.0", "@angular/http": "2.0.0-rc.4", ...

Can you merge two TypeScript objects with identical keys but different values?

These TypeScript objects have identical keys but different properties. My goal is to merge the properties from one object onto the other. interface Stat<T, V> { name: string; description: string; formatValue: (params: { value: V; item: T }) =&g ...