🚀 Guia Pas a Pas: Implementació de Login amb Angular i JWT¶
Aquesta guia explica detalladament com crear des de zero una aplicació Angular que implementi autenticació mitjançant JWT (JSON Web Token), utilitzant les millors pràctiques d'Angular 17+ (Standalone Components, Signals, Interceptors).
Requisits Previs
- Node.js instal·lat (v18.13 o superior recomanat).
- Coneixements bàsics de TypeScript i HTML/CSS.
- Una API Backend funcionant que retorni un JWT (com la del projecte servidor).
1. Creació del Projecte¶
El primer pas és generar una nova aplicació Angular. Utilitzarem l'opció --no-standalone si volem mòduls o, com recomanem ara, per defecte (Standalone).
ng new client-angular --style=scss --routing
cd client-angular
Estructura de Carpetes
Organitza el teu codi des del principi. Recomanem aquesta estructura dins de src/app/:
components/: Vistes (Login, Users, etc.)services/: Lògica de negoci i HTTP.models/: Interfícies TypeScript.interceptors/: Manipulació global de peticions.guards/: Protecció de rutes.
2. Instal·lació de Llibreries UI (Opcional però Recomanat)¶
Per tenir una interfície professional ràpidament, instal·lem Angular Material.
ng add @angular/material
- Tria un tema (ex: "Deep Purple/Amber" o "Custom").
- Accepta les tipografies i animacions globals.
3. Definició de Models (TypeScript)¶
Abans de programar lògica, definim què estem movent. Crea src/app/models/user.model.ts.
ng g m models/user
export interface User {
id: number;
username: string;
email: string;
}
export interface LoginRequest {
username: string;
password: string;
}
export interface JwtResponse {
token: string;
message?: string;
}
4. Implementació de Serveis (La Lògica)¶
4.1. AuthService¶
Aquest servei gestionarà l'estat de l'usuari i el localStorage.
ng g s services/auth
// src/app/services/auth.service.ts
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject, tap } from 'rxjs';
import { LoginRequest, JwtResponse } from '../models/user.model';
@Injectable({ providedIn: 'root' })
export class AuthService {
private http = inject(HttpClient);
private apiUrl = 'http://localhost:8080/api/auth'; // Ajusta al teu backend
// Gestiona l'estat: Estic loguejat? Qui sóc?
private currentUserSubject = new BehaviorSubject<string | null>(localStorage.getItem('token'));
public currentUser$ = this.currentUserSubject.asObservable();
login(credentials: LoginRequest) {
return this.http.post<JwtResponse>(`${this.apiUrl}/login`, credentials).pipe(
tap(response => {
// Guardem al navegador i notifiquem a l'app
localStorage.setItem('token', response.token);
this.currentUserSubject.next(response.token);
})
);
}
logout() {
localStorage.removeItem('token');
this.currentUserSubject.next(null);
}
isLoggedIn(): boolean {
return !!localStorage.getItem('token');
}
}
5. Components: Login UI¶
Crea el component de login: ng g c components/login.
LoginComponent (Lògica .ts)
@Component({
//... imports: [MatCardModule, MatInputModule, FormsModule, ReactiveFormsModule]
standalone: true,
//...
})
export class LoginComponent {
private authService = inject(AuthService);
private router = inject(Router);
credentials = { username: '', password: '' };
onSubmit() {
this.authService.login(this.credentials).subscribe({
next: () => this.router.navigate(['/users']),
error: (err) => console.error('Error de login', err)
});
}
}
El template HTML hauria de tenir un formulari que faci servir [(ngModel)] o formControl per lligar les dades amb credentials.
6. La Seguretat: Interceptor HTTP¶
Com enviem el token automàticament? No l'afegeixis manualment a cada petició. Fes servir un Interceptor.
// src/app/interceptors/auth.interceptor.ts
import { HttpInterceptorFn } from '@angular/common/http';
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const token = localStorage.getItem('token');
if (token) {
// Clonem la petició perquè són immutables
const cloned = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next(cloned);
}
return next(req);
};
Important: Registra'l a app.config.ts:
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(withInterceptors([authInterceptor]))
// ... altres providers
]
};
7. Protecció de Rutes: Guards¶
Volem prohibir l'entrada a /users si no estàs loguejat.
// src/app/guards/auth.guard.ts
import { CanActivateFn, Router } from '@angular/router';
import { inject } from '@angular/core';
import { AuthService } from '../services/auth.service';
export const authGuard: CanActivateFn = (route, state) => {
const authService = inject(AuthService);
const router = inject(Router);
if (authService.isLoggedIn()) {
return true;
} else {
router.navigate(['/login']);
return false;
}
};
Aplica-ho a app.routes.ts:
export const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'users', component: UsersComponent, canActivate: [authGuard] },
{ path: '', redirectTo: '/login', pathMatch: 'full' }
];
8. Resum del Flux¶
- L'usuari entra a
/login➡️ Introdueix dades. AuthServiceenvia POST al backend.- Si és OK, guarda el
tokenalocalStorage. - L'usuari va a
/users. AuthGuardcomprova el token ➡️ Deixa passar.UsersComponentdemana la llista d'usuaris.AuthInterceptorintercepta la petició i li posa el barret (header) del Token.- El servidor valida el token i retorna les dades privades.
Felicitats!
Has implementat un sistema d'autenticació professional i segur amb Angular 17+! 🚀
