Article
· Oct 9, 2023 5m de lecture

QuinielaML - Comment utiliser l'authentification JWT

En profitant de l'application Quiniela ML et comme nous l'avons dit dans l'article précédent, nous allons expliquer comment nous pouvons réaliser une authentification JWT entre notre frontend développé en Angular et notre backend développé en InterSystems IRIS.

Je vous rappelle l'architecture de notre projet QuinielaML :

Pour les applications web, le développement de l'administration et de la gestion de l'accès des utilisateurs est généralement un processus compliqué, mais dans notre cas, InterSystems IRIS le simplifie en nous fournissant toute l'infrastructure dont nous avons besoin.

Authentification par jeton Web JSON

IRIS permet aux applications web connectées à l'instance déployée de se connecter via JWT de manière simple et directe.

Rappelons le cycle de vie d'une demande d'authentification JWT :

Flux d'authentification du client-serveur JWT

En ce qui nous concerne, le client sera notre application frontend développée en Angular et le serveur sera notre instance IRIS.

Ainsi, le processus commence par l'envoi de la demande de connexion du client au serveur. Le serveur valide les données de l'utilisateur en générant un jeton au format JSON qu'il renvoie à l'application cliente. Le client peut à son tour valider le jeton reçu et doit ensuite l'inclure dans l'en-tête de ses appels au serveur afin d'obtenir les ressources demandées.

Comme nous l'avons dit, IRIS facilite la gestion de l'authentification via JWT et pour cela il nous fournit les endpoints suivants à utiliser par notre application client :

  • /login — Un appel à ce point de terminaison avec l'authentification HTTP de base ou avec des informations d'identification valides dans le corps de la demande renvoie un jeton d'accès et un jeton d'actualisation qui peuvent être utilisés dans des demandes ultérieures.
  • /logout — Un appel à ce point de terminaison, s'il n'utilise pas Group-By-ID, invalide le jeton d'accès fourni et le jeton d'actualisation associé. S'il utilise Group-By-ID, toutes les sessions du groupe By-ID actuel sont invalidées.
  • /refresh — Un appel à ce point de terminaison émet une nouvelle paire de jetons d'accès et d'actualisation lorsque l'appel est effectué avec un jeton d'actualisation valide. Cela invalide la paire de jetons d'accès et d'actualisation précédente.
  • /revoke — Si le Group-By-ID n'est pas utilisé, ceci est fonctionnellement le même que /logout. Si l'on utilise Group-By-ID, cela révoque uniquement la paire de jetons d'accès et d'actualisation en cours.
  • Configuration frontale de la connexion

    Comme nous l'avons déjà précisé, nous avons développé le frontend de notre application en utilisant Angular. Depuis notre page HTML login.component.html, nous avons configuré un formulaire qui accepte le nom d'utilisateur et le mot de passe et nous procédons, depuis la classe TypeScript, au lancement de l'invocation depuis le composant de services que nous avons défini.

    Ici, nous voyons comment nous invoquons l'appel au service à partir de login.component.ts :

    onSubmit(): void {
        const { username, password } = this.form;
    
        this.authService.login(username, password).subscribe({
          next: data => {
            this.storageService.save(data.access_token)
            this.isLoggedIn = true;
            this.router.navigate(['home']);
          },
          error: err => {
          }
        });
    }

    Voyons maintenant l'appel que nous lançons depuis le service auth.service.ts vers notre backend :

    login(username: string, password: string): Observable<any> {
        return this.http.post<Response>(
          AUTH_API + 'login',
          {
            "user": username,
            "password": password,
          },
          httpOptions
        )
    }

    Comme vous le voyez, nous avons défini notre appel au point de terminaison login à partir duquel nous récupérerons la réponse et stockerons l'access_token pour authentifier ultérieurement nos appels.

    Le stockage du jeton reçu en réponse sera effectué par le service storage.service.ts :

    save(userToken: string): void {
        window.sessionStorage.setItem(USER_KEY, userToken);
    }

    Avec notre jeton stocké, il nous suffit d'intercepter chaque requête envoyée à IRIS et d'insérer le jeton dans l'en-tête. Pour ce faire, nous allons définir un HttpInterceptor dans la classe auth.interceptor.ts.

    intercept(req: HttpRequest<any>, next: HttpHandler) {
        // Get the auth token from the service.
        const authToken = this.storageService.getToken();
    
        // Clone the request and replace the original headers with
        // cloned headers, updated with the authorization.
        if (authToken !== ''){
            req = req.clone({
                headers: req.headers.set('Authorization', 'Bearer ' + authToken)
              });
        }
        // send cloned request with header to the next handler.
        return next.handle(req);
    }

    Configuration de l'authentification JWT dans IRIS

    Pour que notre IRIS puisse fournir ces services, nous devons configurer correctement notre application web et pour cela nous y accéderons à partir de l'option de menu Administration -> Security -> Applications -> Web Applications (Administration -> Sécurité -> Applications -> Applications web).

    Lorsque nous sommes dans la configuration de l'application, nous devons marquer l'utilisation de l'authentification JWT et nous pouvons définir le délai d'attente pour le jeton d'accès et le jeton d'actualisation :

    Avec cette configuration, nous n'aurons besoin de rien d'autre pour commencer à utiliser ce mode d'authentification dans nos applications web.

    Un commentaire sur la configuration ou l'utilisation de l'authentification JWT est toujours bienvenu si vous avez des questions à ce sujet.

    Le prochain article présentera la configuration de notre projet QuinielaML pour effectuer du web scraping en utilisant Embedded Python.

    Discussion (0)1
    Connectez-vous ou inscrivez-vous pour continuer