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.
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