Publié le : 29/01/2023

Authentification sous Angular en utilisant le REST API et JWT

Anuglar Authentification REST API JWT

Ce tutoriel fait suite au tutoriel qui s’intitule Codeigniter 4 RESTful API authentification en utilisant JWT.

Plusieurs définition ont été donné à savoir le JWT, l’API REST.

Dans ce qui suit, nous allons mettre en place un système d’authentification sous Angular en utilisant le REST API et JWT.

Nous tenons à mentionner ici que ce qui suit peut être couplé avec d’autres outils de backend d’authentification. Pour notre cas ici, nous l’avons couplé avec l’authentification avec Codeigniter 4. Mais on peut le coupler avec Python, .Net, Java, etc… Mais il faut qu’il utilise le token web JWT.

Installation et configuration du projet Angular

Pour la création d’un projet sous Angular, vous pouvez voir l’article que nous avons écrit dessus qui s’intitule : Un simple projet Angular.

Mais en résumé pour créer un projet Angular, nous pouvons exécuter la commande :

ng new angular-meanstack-authentication

Création du composant d’authentification

Nous allons par la suite créer un composant d’authentification signin avec la commande :

ng g c auth/signin

Configuration de HttpClient dans le projet

Pour gérer les API REST via des demandes HTTP dans notre application d’authentification sous Angular, nous devons importer le service Angular HttpClient dans le module d’authentification.

Pour ce faire, nous allons importer le service HttpClientModule dans le fichier TypeScript app.module.ts.

import { HttpClientModule } from '@angular/common/http';
@NgModule({
  imports: [
    HttpClientModule
   ]
})

Création d’un service d’authentification sous Angular

Dans un premier temps, nous allons créer une interface Utilisateur dans le fichier app/types/utilisateur.ts qui va définir la structure de l’utilisateur. Le code correspondant est :

export interface Utilisateur {
    id: number | null,
    username: string | null,
    email: string | null,
    password: string | null,
}

Par la suite, nous allons créer le service Angular Utilisateur pour récupérer les données de l’utilisateur via le REST API. Nous aurons alors, dans le fichier app/shared/utilisateur.service.ts le coce ci-dessous :

import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { catchError, map, Observable, throwError } from 'rxjs';
import { User } from '../types/user';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  endpoint: string = '/api';
  headers = new HttpHeaders().set('Content-Type', 'application/json');
  currentUser = {};
  constructor(private http: HttpClient, public router: Router) {}
  // Sign-up
  signUp(user: Utilisateur): Observable<any> {
    let api = `${this.endpoint}/register-user`;
    return this.http.post(api, user).pipe(catchError(this.handleError));
  }
  // Sign-in
  signIn(user: Utilisateur) {
    return this.http
      .post<any>(`${this.endpoint}/login`, user)
      .subscribe((res: any) => {
        localStorage.setItem('access_token', res.token);
        this.router.navigate(["/"])
        // this.getUserProfile(res._id).subscribe((res) => {
        //   this.currentUser = res;
        //   this.router.navigate(['user-profile/' + res.msg._id]);
        // });
      });
  }
  getToken() {
    return localStorage.getItem('access_token');
  }
  get isLoggedIn(): boolean {
    let authToken = localStorage.getItem('access_token');
    return authToken !== null ? true : false;
  }
  doLogout() {
    let removeToken = localStorage.removeItem('access_token');
    if (removeToken == null) {
      this.router.navigate(['log-in']);
    }
  }
  // User profile
  getUserProfile(id: any): Observable<any> {
    let api = `${this.endpoint}/user-profile/${id}`;
    return this.http.get(api, { headers: this.headers }).pipe(
      map((res) => {
        return res || {};
      }),
      catchError(this.handleError)
    );
  }
  // Error
  handleError(error: HttpErrorResponse) {
    let msg = '';
    if (error.error instanceof ErrorEvent) {
      // client-side error
      msg = error.error.message;
    } else {
      // server-side error
      msg = `Error Code: ${error.status}\nMessage: ${error.message}`;
    }
    return throwError(msg);
  }  
  public deconnecter(){
    localStorage.removeItem('access_token');
  }
}

Ce qui nous intéresse dans l’exemple de code ci-dessus, c’est la fonction signIn. C’est cette fonction qui va envoyer la demande d’authentification à notre REST API via l’URL /login. Les paramètres du REST API seront les paramètres d’authentification de l’utilisateur, à savoir :

  • son login;
  • son mot de passe.

Une fois que l’authentification est faite, le token JWT est enregistré dans le navigateur de l’utilisateur.

Définir le jeton JWT avec l’HttpInterceptor d’Angular

Nous allons, par la suite, le jeton web JWT dans l’entête HTTP en utilisant l’HttpInterceptor d’Angular. Pour ce faire, nous allons créer un fichier qui va se nommer authconfig.interceptor.ts, et nous allons mettre le code ci-dessous à l’intérieur :

import { Injectable } from "@angular/core";
import { HttpInterceptor, HttpRequest, HttpHandler } from "@angular/common/http";
import { AuthService } from "./auth.service";
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    constructor(private authService: AuthService) { }
    intercept(req: HttpRequest<any>, next: HttpHandler) {
        const authToken = this.authService.getToken();
        req = req.clone({
            setHeaders: {
                Authorization: "Bearer " + authToken
            }
        });
        return next.handle(req);
    }
}

L’authentification via JWT nécessite de définir un Bearer pour l’autorisation.

Par la suite, nous allons importer HTTP_INTERCEPTORS dans le fichier app.module.ts. Ainsi nous aurons à l’intérieur du fichier un code du genre :

import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthInterceptor } from './shared/authconfig.interceptor';
@NgModule({
  declarations: [...],
  imports: [HttpClientModule],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthInterceptor,
      multi: true
    }
  ],
  bootstrap: [...]
})
export class AppModule { }

Protéger tous les routes en utilisant canActivate pour l’authentification sous Angular avec le REST API et JWT

Tous les routes peuvent être protéger avec canActivate. Tous les utilisateurs qui n’auront pas le droit n’auront pas accès aux URL qui sont protégés par canActivate. Pour implémenter l’interface canActivate, il faut exécuter la commande :

ng g guard shared/auth

Nous aurons un fichier qui aura pour nom auth.guard.ts, et nous aurons à l’intérieur :

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(
    public authService: AuthService,
    public router: Router
  ) { }
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    if (this.authService.isLoggedIn !== true) {
      window.alert("Access not allowed!");
      this.router.navigate(['log-in'])
    }
    return true;
  }
  
}

Maintenant, il faut importer l’interface AuthGuard et l’injecter dans app-routing.module.ts comme ci-dessous :

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { SigninComponent } from './auth/signin/signin.component';
import { SignupComponent } from './auth/signup/signup.component';
import { TypeComponent } from './parametrage/type/type.component';
import { AuthGuard } from "./shared/auth.guard";
import { TmpComponent } from './tmp/tmp.component';

const routes: Routes = [
  { path: '', redirectTo: '/type-tiers', pathMatch: 'full' },
  { path: 'log-in', component: SigninComponent },
  { path: 'type', component: TypeComponent, canActivate: [AuthGuard] }
];
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
Les mots clés rattachés à cet article : Angular  -  JWT  -  Rest api

Nos clients

Une vingtaine de clients nationaux et internationaux