Decodificar tokens JWT en Angular

Avanzado
Angular
Angular
Actualizado: 27/08/2024

¡Desbloquea el curso completo!

IA
Ejercicios
Certificado
Entrar

Introducción

Un token JWT (JSON Web Token) es un estándar abierto (RFC 7519) que define una forma compacta y autónoma de transmitir información de forma segura entre partes como un objeto JSON. Esta información puede ser verificada y de confianza porque está firmada digitalmente. 

¿Te está gustando esta lección?

Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.

Progreso guardado
Asistente IA
Ejercicios
Iniciar sesión gratis

Más de 25.000 desarrolladores ya confían en CertiDevs

En aplicaciones donde el frontend está desacoplado del backend es habitual utilizar seguridad basada en tokens JWT.

Creación de interfaces para recibir token JWT

Crear el archivo token.dto.ts para guardar las interfaces relativas a la gestión de tokens:

// Respuesta del backend con el token JWT tras hacer login exitoso
export interface Token {
  token: string;
}

// Token JWT decodificado para acceder a sus datos
export interface DecodedToken {
  sub: number;
  email: string;
  role: string;
  iat: number;
  exp: number;
}

Creación de servicio de autenticación

Creamos un servicio llamado AuthenticationService con el siguiente comando:

ng generate service authentication/authentication

Este servicio será el encargado de almacenar el estado de autenticación del usuario en la aplicación.

Guardar el token JWT

@Injectable({
  providedIn: 'root'
})
export class AuthenticationService {

  isLoggedIn = new BehaviorSubject<boolean>(this.hasToken());

  hasToken(): boolean {
    return localStorage.getItem("jwt_token") !== null;
  }
  
 // Este método se invoca tras hacer login en login.component.ts
  handleLogin(token: string) {
    // guardar el token en el almacenamiento del navegador
    localStorage.setItem("jwt_token", token);
    this.isLoggedIn.next(true);

  }
}

Saber si el usuario está autenticado

En la propia barra de navegación o navbar.component.ts es posible detectar si el usuario tiene un token (se ha autenticado con login).

En base al token mostramos un botón de Iniciar sesión o Cerrar sesión.

navbar.component.ts:

@Component({
  selector: 'app-navbar',
  standalone: true,
  imports: [RouterLink, RouterLinkActive, NgbDropdownModule],
  templateUrl: './navbar.component.html',
  styleUrl: './navbar.component.css'
})
export class NavbarComponent {

  isLoggedIn = false;
  
    constructor(
    private authService: AuthenticationService,
    private router: Router
    ) {
    // Esto permite que el componente Navbar se entere de que ha ocurrido un login exitoso
    this.authService.isLoggedIn.subscribe(isLoggedIn => this.isLoggedIn = isLoggedIn);

  }
}

En el archivo navbar.component.html se puede utilizar el boolean isLoggedIn con un if para determinar si mostrar botones de Mi cuenta y Logout o botones de Iniciar Sesión y Registro.

   @if(isLoggedIn) {
          <button type="button" class="btn btn-warning ms-2" (click)="logout()">
            Logout
            <i class="bi bi-box-arrow-right ms-2"></i>
          </button>
        } @else {
          <button type="button" class="btn btn-success ms-2" routerLink="/login">
            Login
            <i class="bi bi-box-arrow-in-right ms-2"></i>
          </button>
          <button type="button" class="btn btn-secondary ms-2" routerLink="/register">
            Registro
            <i class="bi bi-person-plus ms-2"></i>
          </button>
        }

Borrar el token JWT para hacer logout

authentication.service.ts se crea un método que elimina el token JWT del localStorage y cambia el boolean isLoggedIn a false.


@Injectable({
  providedIn: 'root'
})
export class AuthenticationService {

  isLoggedIn = new BehaviorSubject<boolean>(this.hasToken());

  handleLogin(token: string) {
    // .... código 

  }
  
  hasToken(): boolean {
    return localStorage.getItem("jwt_token") !== null;
  }
  
  // Este método se invoca desde el botón "Cerrar sesión" de la navbar
  logout() {
    localStorage.removeItem("jwt_token"); // Elimina el token
    this.isLoggedIn.next(false);

  }
}

Decodificar el token JWT

Primero instalamos la librería jwt-decode para poder decodificar el token y extraer la información que contiene como por ejemplo: id, email, rol del usuario.

npm install jwt-decode

Comprobar si la librería se ha agregado al proyecto revisando el archivo package.json:

Si estamos trabajando en un proyecto con más personas, las otras deberán ejecutar el comando:

 npm install 

Esto garantiza que todos los miembros del equipo descargan las librerías y pueden utilizarlas.

Usar el método jwtDecode() en el AuthenticationService para decodificar el token JWT:

  userEmail = new BehaviorSubject<string>(this.getCurrentEmail());

  // Método para extraer el email del token JWT
  getCurrentEmail() {
    // decodificar el token y extraer la información que tiene dentro
    const token = localStorage.getItem("jwt_token");
    if(!token) return '';

    const decodedToken = jwtDecode(token) as DecodedToken; // DecodedToken en token.dto.ts
    return decodedToken.email;
  }
  
  // Actualizar el método de login para que obtenga el email:
  handleLogin(token: string) {
    // guardar el token en el almacenamiento del navegador
    localStorage.setItem("jwt_token", token);
    this.isLoggedIn.next(true);
    this.userEmail.next(this.getCurrentEmail());

  }

Si guardamos el email en una variable BehaviourSubject entonces podemos utilizarlo en otros lugares de la plataforma, por ejemplo para mostrarlo en la navbar y que el usuario sepa cuál es su cuenta con su email.

Luego en la navbar.component.ts se puede suscribir a userEmail y mostrar el email si existe. Ejemplo:

    this.authService.userEmail.subscribe(userEmail => this.userEmail = userEmail);

Extraer el rol del token JWT

Actualizar el AuthenticationService para detectar si el usuario es administrador:

   isAdmin = new BehaviorSubject<boolean>(this.getIsAdmin());

   getIsAdmin() {
    const token = localStorage.getItem("jwt_token");
    if(!token) return false;

    const decodedToken = jwtDecode(token) as DecodedToken;
    return decodedToken.role === 'admin'; // true o false
  }

Luego esta variable isAdmin es posible suscribirse a ella desde la navbar o cualquier otro componente de la aplicación.

Código final AuthenticationService

Este es el resultado final del archivo authentication.service.ts:

@Injectable({
  providedIn: 'root'
})
export class AuthenticationService {

  // Comprueba si un usuario ya está logueado, es decir, existe token
  // Notifica a quien se haya suscrito a este booleano de que ha ocurrido un login
  isLoggedIn = new BehaviorSubject<boolean>(this.hasToken());
  userEmail = new BehaviorSubject<string>(this.getCurrentEmail());
  isAdmin = new BehaviorSubject<boolean>(this.getIsAdmin());

  hasToken(): boolean {
    return localStorage.getItem("jwt_token") !== null;
  }
  handleLogin(token: string) {
    // guardar el token en el almacenamiento del navegador
    localStorage.setItem("jwt_token", token);
    this.isLoggedIn.next(true);
    this.userEmail.next(this.getCurrentEmail());
    this.isAdmin.next(this.getIsAdmin());
  }
  getCurrentEmail() {
    // decodificar el token y extraer la información que tiene dentro
    const token = localStorage.getItem("jwt_token");
    if(!token) return '';

    const decodedToken = jwtDecode(token) as DecodedToken;
    return decodedToken.email;
  }
  getIsAdmin() {
    const token = localStorage.getItem("jwt_token");
    if(!token) return false;

    const decodedToken = jwtDecode(token) as DecodedToken;
    return decodedToken.role === 'admin'; // true o false
  }
  logout() {
    localStorage.removeItem("jwt_token");
    this.isLoggedIn.next(false);
    this.userEmail.next('');
    this.isAdmin.next(false);
  }

}

Aprendizajes de esta lección

  • Obtener token JWT
  • Decodificar token JWT
  • Notificar a navbar de que el usuario se ha autenticado
  • Notificar a navbar de cuál es el email del usuario
  • Login y Logout

Completa Angular y certifícate

Únete a nuestra plataforma y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.

Asistente IA

Resuelve dudas al instante

Ejercicios

Practica con proyectos reales

Certificados

Valida tus conocimientos

Más de 25.000 desarrolladores ya se han certificado con CertiDevs

⭐⭐⭐⭐⭐
4.9/5 valoración