Angular

Angular

Tutorial Angular: Seguridad JWT en Angular

Angular JWT: autenticación y uso. Aprende a implementar JWT en Angular para autenticación segura con ejemplos prácticos y detallados.

Introducción a JWT

Los JSON Web Tokens (JWT) en Angular son cruciales para desarrolladores que buscan implementar autenticación y autorización seguras en sus aplicaciones web. JWT ofrece una manera compacta y autónoma de transmitir información segura entre partes como un objeto JSON. Esta información puede ser verificada y confiada porque está firmada digitalmente. Angular, siendo uno de los frameworks más populares para el desarrollo de aplicaciones web, proporciona un ecosistema adecuado para integrar JWT en la gestión de sesiones de usuario.

Historia y origen de JWT

JSON Web Tokens (JWT) surgieron como una solución a la necesidad de un estándar de tokens de acceso que permitiera la comunicación entre diferentes sistemas de manera segura. Su especificación, definida en el RFC 7519, establece cómo los tokens pueden ser usados para intercambiar información entre dos partes de manera segura. Esta característica los ha hecho sumamente populares en la implementación de autenticación y autorización en aplicaciones web modernas, incluyendo aquellas desarrolladas con Angular.

Los JWT son importantes porque proporcionan un método estandarizado y ligero para la autenticación de usuarios y la autorización de solicitudes, sin necesidad de mantener un estado de sesión en el servidor. Esto es especialmente útil en arquitecturas de aplicaciones distribuidas y microservicios. Además, su capacidad para ser firmados digitalmente asegura que la información que contienen puede ser verificada y confiada sin necesidad de una consulta adicional al servidor de autenticación.

Diferenciación de JWT de otros métodos de autenticación

Los JSON Web Tokens (JWT) representan un avance significativo en la autenticación y autorización de aplicaciones web comparados con métodos tradicionales, como las sesiones basadas en cookies. 

A diferencia de las cookies, que requieren almacenamiento del estado de la sesión en el servidor, los JWT son autónomos y contienen toda la información necesaria para verificar la identidad del usuario. Esta característica los hace ideales para aplicaciones escalables y distribuidas, donde mantener el estado de la sesión entre múltiples servidores puede ser problemático. 

Además, los JWT pueden ser fácilmente transmitidos entre diferentes dominios y servicios, facilitando patrones de diseño como Single Sign-On (SSO) y comunicaciones entre microservicios, lo que contribuye a su popularidad y adopción generalizada en la industria.

Aplicaciones prácticas

  • Autenticación de usuario: En aplicaciones Angular, los JWT se usan comúnmente para autenticar usuarios. Después de que un usuario se autentica, el servidor genera un JWT que luego se devuelve al cliente y se almacena, típicamente en el almacenamiento local del navegador.
  • Autorización de solicitudes: Los JWT son enviados en los encabezados de las solicitudes HTTP para acceder a recursos protegidos en el servidor, permitiendo una fácil autorización de solicitudes basada en tokens.
  • Single Sign-On (SSO): Los JWT son una base para implementar SSO, permitiendo que los usuarios se autentiquen una vez y accedan a varios servicios sin necesidad de volver a autenticarse.

Implementación JWT en Angular

La autenticación con JWT implica dos partes principales: el proceso de inicio de sesión, donde el servidor valida las credenciales del usuario y genera un token; y el uso del token para futuras solicitudes que requieran autenticación. En Angular, este proceso se maneja a través de servicios y componentes que interactúan con el backend y almacenan el token en el cliente.

Paso 1: Crear el servicio de autenticación auth.service.ts

El AuthService es el corazón de nuestro sistema de autenticación. Este servicio se encarga de:

  • Enviar las credenciales del usuario al servidor y recibir el JWT.
  • Almacenar el JWT de manera segura en el almacenamiento local del navegador.
  • Proveer un mecanismo para verificar si el usuario está autenticado.

Implementación:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  private isLoggedIn = new BehaviorSubject<boolean>(false);

  constructor(private http: HttpClient) {}

  // Inicia sesión y almacena el JWT
  login(username: string, password: string) {
    return this.http.post<{token: string}>('https://yourapi.com/login', { username, password })
      .pipe(
        tap(response => {
          localStorage.setItem('access_token', response.token); // Almacena el token
          this.isLoggedIn.next(true); // Actualiza el estado de autenticación
        })
      );
  }

  // Verifica si el usuario está autenticado
  isAuthenticated() {
    return this.isLoggedIn.asObservable();
  }
}

Puntos clave:

  • BehaviorSubject<boolean>: Mantiene el estado de autenticación que puede ser consumido por otros componentes o servicios.
  • localStorage.setItem('access_token', response.token): Almacena el token en el almacenamiento local, asegurando que permanezca disponible durante las sesiones del navegador.

Paso 2: Crear componente de inicio de sesión

El componente de inicio de sesión proporciona una interfaz de usuario para que los usuarios ingresen sus credenciales. Interactúa con el AuthService para iniciar la sesión.

Implementación:

import { Component } from '@angular/core';
import { AuthService } from '../auth.service';

@Component({
  selector: 'app-login',
  template: `
    <form (submit)="login()">
      <input type="text" [(ngModel)]="username" name="username" placeholder="Username">
      <input type="password" [(ngModel)]="password" name="password" placeholder="Password">
      <button type="submit">Login</button>
    </form>
  `
})
export class LoginComponent {
  username: string = '';
  password: string = '';

  constructor(private authService: AuthService) {}

  // Función de inicio de sesión que utiliza AuthService
  login() {
    this.authService.login(this.username, this.password).subscribe();
  }
}

Puntos clave:

  • Formulario de inicio de sesión: Recoge las credenciales del usuario y las envía al AuthService.
  • Modelo de Two-Way Binding con [(ngModel)]: Permite una interacción fluida entre la vista (formulario) y el componente.

Otra opción es crear un formulario reactivo:

  <form [formGroup]="loginForm" (ngSubmit)="save()">
    <h1 class="h3 mb-3 fw-normal">Iniciar sesión</h1>
    <div class="form-floating">
      <input type="email" class="form-control" id="email" placeholder="name@example.com" formControlName="email">
      <label for="email">Email address</label>
    </div>
    <div class="form-floating">
      <input type="password" class="form-control" id="password" placeholder="Password" formControlName="password">
      <label for="password">Password</label>
    </div>
    <button class="btn btn-primary w-100 py-2" type="submit">Iniciar sesión</button>
    @if(errorMessage && errorMessage.length > 0) {
      <small class="text-danger">{{errorMessage}}</small>
    } 
  </form>

Paso 3: Crear el Interceptor auth.interceptor.ts

Este interceptor interceptará todas las solicitudes HTTP salientes. Si existe un JWT almacenado (por ejemplo, en el almacenamiento local del navegador), el interceptor añadirá este token al encabezado de autorización de cada solicitud.

Implementación:

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const token = localStorage.getItem('access_token'); // Obtiene el JWT del almacenamiento local
    if (token) {
      // Si existe un token, clona la solicitud y añade el encabezado de autorización
      const cloned = req.clone({
        headers: req.headers.set("Authorization", "Bearer " + token)
      });
      return next.handle(cloned); // Pasa la solicitud modificada al siguiente manejador
    } else {
      return next.handle(req); // Pasa la solicitud original al siguiente manejador si no hay token
    }
  }
}

Puntos clave:

  • localStorage.getItem('access_token'): Recupera el token de autenticación del almacenamiento local.
  • req.clone({...}): Crea una copia de la solicitud original y modifica los encabezados para incluir el token de autenticación.

Paso 4: Registrar el interceptor en el módulo principal app.module.ts

Para que el interceptor sea efectivo, debe ser registrado en el módulo principal de la aplicación Angular (AppModule). Esto se hace proporcionando el interceptor como un proveedor en el nivel de módulo.

Implementación:

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthInterceptor } from './auth.interceptor';

@NgModule({
  declarations: [
    // Otros componentes
  ],
  imports: [
    // Otros módulos
  ],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
    // Añade aquí otros servicios si es necesario
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Puntos clave:

  • HTTP_INTERCEPTORS: Un token de inyección especial de Angular que permite a los interceptores ser agregados a la cadena de manejo de solicitudes.
  • multi: true: Indica que HTTP_INTERCEPTORS es un token multi-proveedor, permitiendo múltiples interceptores que se ejecutan en el orden en que fueron proporcionados.
Certifícate en Angular con CertiDevs PLUS

Ejercicios de esta lección Seguridad JWT en Angular

Evalúa tus conocimientos de esta lección Seguridad JWT en Angular con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Signals en Angular

Angular
Puzzle

Guards funcionales

Angular
Test

Decodificar JWT en Angular

Angular
Test

Servicio con HttpClient

Angular
Código

Ciclo de vida de componentes en Angular

Angular
Test

Gestión de productos de Fake Store API

Angular
Proyecto

Data binding en Angular

Angular
Test

Routes sin módulos en Angular

Angular
Código

Router en Angular

Angular
Test

Instalación de Angular

Angular
Puzzle

Route Guards basados en interfaces

Angular
Código

La directiva @if en Angular

Angular
Puzzle

Formularios reactivos en Angular

Angular
Código

Servicios en Angular

Angular
Puzzle

Interceptor funcional

Angular
Test

Servicio con Array

Angular
Código

La directiva @for en Angular

Angular
Puzzle

Interceptores HTTP

Angular
Código

Componentes standalone true

Angular
Puzzle

Formularios con ngModel en Angular

Angular
Puzzle

Routes en Angular

Angular
Test

Comunicación entre componentes Angular

Angular
Test

Parámetros en rutas con ActivatedRoute

Angular
Test

CRUD de Restaurantes y Platos

Angular
Proyecto

Tablas en Angular Material

Angular
Puzzle

Formulario de registro de usuarios

Angular
Proyecto

Instalación y uso de NgBoostrap

Angular
Puzzle

Desarrollo de componentes Angular

Angular
Test

JWT en Angular

Angular
Código

Formularios reactivos en Angular

Angular
Puzzle

Formularios en Angular Material

Angular
Puzzle

Layout con Angular Material

Angular
Puzzle

Effects en Angular

Angular
Test

Data binding

Angular
Código

HttpClient en servicios de Angular

Angular
Puzzle

Desarrollo de módulos Angular

Angular
Puzzle

Comandos Angular CLI

Angular
Puzzle

Subir archivo en formularios

Angular
Test

La directiva routerLink en Angular

Angular
Test

Todas las lecciones de Angular

Accede a todas las lecciones de Angular y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Instalación Angular

Angular

Introducción Y Entorno

Comandos Angular Cli

Angular

Introducción Y Entorno

Desarrollo De Componentes Angular

Angular

Componentes

Data Binding En Angular

Angular

Componentes

Ciclo De Vida De Componentes En Angular

Angular

Componentes

Comunicación Entre Componentes Angular

Angular

Componentes

La Directiva @If En Angular

Angular

Componentes

La Directiva @For En Angular

Angular

Componentes

Componentes Standalone

Angular

Componentes

Desarrollo De Módulos Angular

Angular

Módulos

Routes En Angular

Angular

Enrutado Y Navegación

Router En Angular

Angular

Enrutado Y Navegación

La Directiva Routerlink En Angular

Angular

Enrutado Y Navegación

Parámetros En Rutas Con Activatedroute

Angular

Enrutado Y Navegación

Routes Sin Módulos En Angular

Angular

Enrutado Y Navegación

Servicios En Angular

Angular

Servicios E Inyección De Dependencias

Httpclient En Servicios De Angular

Angular

Servicios E Inyección De Dependencias

Formularios Con Ngmodel En Angular

Angular

Formularios

Formularios Reactivos En Angular

Angular

Formularios

Subir Archivo En Formularios

Angular

Formularios

Layout Con Angular Material

Angular

Integración Con Angular Material

Tablas En Angular Material

Angular

Integración Con Angular Material

Formularios En Angular Material

Angular

Integración Con Angular Material

Instalación Y Uso De Ngboostrap

Angular

Integración Con Bootstrap Css

Signals En Angular

Angular

Signals Y Reactividad

Effects En Angular

Angular

Signals Y Reactividad

Route Guards Basados En Interfaces

Angular

Autenticación Y Autorización

Guards Funcionales

Angular

Autenticación Y Autorización

Interceptores Http Basados En Interfaz

Angular

Autenticación Y Autorización

Interceptores Http Funcionales

Angular

Autenticación Y Autorización

Seguridad Jwt En Angular

Angular

Autenticación Y Autorización

Decodificar Tokens Jwt En Angular

Angular

Autenticación Y Autorización

Certificados de superación de Angular

Supera todos los ejercicios de programación del curso de Angular y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  1. Comprender el concepto y la estructura de JWT.
  2. Integrar JWT en aplicaciones Angular.
  3. Autorización y protección de rutas con JWT.
  4. Uso de interceptores HTTP para añadir JWT a solicitudes.
  5. Creación y validación de JWT en el servidor.