slogan3

Help me bij het implementeren van een aangepaste Angular-authenticatiestrategie met JWT

description

Door deze gids te volgen, verbeter je de beveiliging van je Angular-toepassing, waardoor veilige gebruikersauthenticatie en sessiebeheer mogelijk worden.

prompt

try_prompt

Gids me door het proces van het maken van een aangepaste authenticatiesysteem in mijn Angular-toepassing dat JSON Web Tokens (JWT) gebruikt. Leg uit hoe je ... more
generate_helper
disclaimerOnPageApi image_legal_disclaimer...

ai_answers

provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een stapsgewijze gids voor het maken van een aangepast authenticatiesysteem in je Angular-toepassing met JWT: 1. Backend-API voorbereiden: - Zorg dat je backend (bijvoorbeeld Node.js met Express) JWT ondersteunt. - Implementeer een login-endpoint dat gebruikersgegevens controleert. - Bij succesvolle login, genereer een JWT met een geheime sleutel en eventuele claims (zoals gebruikers-ID, rol). - Stuurt de JWT terug naar de client in de respons, meestal in de JSON-body of als HTTP-only cookie. 2. Angular-service voor authenticatie maken: - Maak een AuthService die verantwoordelijk is voor login, logout, token opslag en verificatie. - Bij login: - Verstuur gebruikersnaam en wachtwoord naar backend via HttpClient. - Ontvang de JWT en sla deze op. - Voor opslag: - Gebruik bijvoorbeeld `localStorage` of `sessionStorage` om de token op te slaan. - Voor meer veiligheid kun je overwegen om de token in een HTTP-only cookie op te slaan, maar dat beperkt de frontend-beheerbaarheid. 3. Token opslaan en beheren: - Na login: `localStorage.setItem('token', token)` - Bij logout: `localStorage.removeItem('token')` - Maak een methode in AuthService om de token op te halen: ```typescript getToken(): string | null { return localStorage.getItem('token'); } ``` 4. Token verificatie: - Bij elke API-aanroep voeg je de JWT toe aan de Authorization-header: ```typescript const headers = new HttpHeaders({ 'Authorization': 'Bearer ' + this.getToken() }); ``` - Backend controleert de token bij elke request via middleware (bijvoorbeeld `express-jwt`). 5. Routebescherming implementeren: - Gebruik Angular's `CanActivate` guards: ```typescript import { Injectable } from '@angular/core'; import { CanActivate, Router } from '@angular/router'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {} canActivate(): boolean { if (this.authService.getToken()) { return true; } else { this.router.navigate(['/login']); return false; } } } ``` - Voeg deze guard toe aan je routes: ```typescript { path: 'beveiligd', component: BeveiligdeComponent, canActivate: [AuthGuard] } ``` 6. Gebruikerssessie beheren: - Controleer of een token aanwezig is om te bepalen of de gebruiker ingelogd is. - Verleng de sessie door de token te laten vervallen of te refreshen (bijvoorbeeld met refresh tokens). - Bij vervaldatum van JWT: backend moet validatie doen en indien verlopen, vraag de gebruiker opnieuw in te loggen. 7. Extra beveiliging: - Gebruik HTTPS om tokens te beveiligen tijdens transmissie. - Voorkom XSS-aanvallen door de opslag van tokens veilig te houden. - Overweeg het gebruik van refresh tokens voor langdurige sessies zonder de hoofd JWT te laten vervallen. Door deze stappen te volgen, zet je een solide en veilig JWT-gebaseerd authenticatiesysteem op in je Angular-toepassing.
provider: deepseek
model: deepseek-chat
Zeker! Ik begeleid je stap voor stap door het opzetten van een JWT-authenticatiesysteem in Angular. Hier is een complete handleiding: ## 1. Vereiste Packages Installeren ```bash npm install @angular/common @angular/core @angular/router npm install @auth0/angular-jwt # Voor JWT-verwerking ``` ## 2. Auth Service Maken ```typescript // auth.service.ts import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { BehaviorSubject, Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; import { JwtHelperService } from '@auth0/angular-jwt'; export interface LoginResponse { token: string; user: { id: number; email: string; name: string; }; } @Injectable({ providedIn: 'root' }) export class AuthService { private readonly TOKEN_KEY = 'access_token'; private currentUserSubject: BehaviorSubject<any>; public currentUser: Observable<any>; private jwtHelper = new JwtHelperService(); constructor(private http: HttpClient) { this.currentUserSubject = new BehaviorSubject<any>( this.getCurrentUserFromToken() ); this.currentUser = this.currentUserSubject.asObservable(); } login(email: string, password: string): Observable<LoginResponse> { return this.http.post<LoginResponse>('/api/auth/login', { email, password }) .pipe( tap(response => { this.storeToken(response.token); this.currentUserSubject.next(response.user); }) ); } logout(): void { localStorage.removeItem(this.TOKEN_KEY); this.currentUserSubject.next(null); } private storeToken(token: string): void { localStorage.setItem(this.TOKEN_KEY, token); } getToken(): string | null { return localStorage.getItem(this.TOKEN_KEY); } isAuthenticated(): boolean { const token = this.getToken(); return !!(token && !this.jwtHelper.isTokenExpired(token)); } private getCurrentUserFromToken(): any { const token = this.getToken(); if (token && !this.jwtHelper.isTokenExpired(token)) { const decodedToken = this.jwtHelper.decodeToken(token); return { id: decodedToken.sub, email: decodedToken.email, name: decodedToken.name }; } return null; } getCurrentUser(): any { return this.currentUserSubject.value; } } ``` ## 3. Auth Guard voor Route Bescherming ```typescript // auth.guard.ts import { Injectable } from '@angular/core'; import { CanActivate, Router, ActivatedRouteSnapshot } from '@angular/router'; import { AuthService } from './auth.service'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {} canActivate(route: ActivatedRouteSnapshot): boolean { if (this.authService.isAuthenticated()) { // Controleer eventuele rol-based toegang const expectedRole = route.data['expectedRole']; if (expectedRole) { const user = this.authService.getCurrentUser(); if (user.role !== expectedRole) { this.router.navigate(['/unauthorized']); return false; } } return true; } this.router.navigate(['/login'], { queryParams: { returnUrl: route.url } }); return false; } } ``` ## 4. HTTP Interceptor voor Automatische Token Toevoeging ```typescript // jwt.interceptor.ts import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse } from '@angular/common/http'; import { Observable, throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { AuthService } from './auth.service'; @Injectable() export class JwtInterceptor implements HttpInterceptor { constructor(private authService: AuthService) {} intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const token = this.authService.getToken(); if (token) { request = request.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); } return next.handle(request).pipe( catchError((error: HttpErrorResponse) => { if (error.status === 401) { // Token is ongeldig of verlopen this.authService.logout(); window.location.reload(); } return throwError(error); }) ); } } ``` ## 5. Login Component ```typescript // login.component.ts import { Component } from '@angular/core'; import { Router, ActivatedRoute } from '@angular/router'; import { AuthService } from '../auth.service'; @Component({ selector: 'app-login', template: ` <form (ngSubmit)="onSubmit()"> <input type="email" [(ngModel)]="email" name="email" placeholder="Email" required> <input type="password" [(ngModel)]="password" name="password" placeholder="Wachtwoord" required> <button type="submit">Inloggen</button> </form> <div *ngIf="error">{{ error }}</div> ` }) export class LoginComponent { email = ''; password = ''; error = ''; returnUrl = ''; constructor( private authService: AuthService, private router: Router, private route: ActivatedRoute ) { this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/'; } onSubmit(): void { this.authService.login(this.email, this.password).subscribe({ next: () => { this.router.navigate([this.returnUrl]); }, error: (error) => { this.error = 'Inloggen mislukt. Controleer je gegevens.'; } }); } } ``` ## 6. App Module Configuratie ```typescript // app.module.ts import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { JwtModule } from '@auth0/angular-jwt'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { AuthService } from './auth.service'; import { JwtInterceptor } from './jwt.interceptor'; import { LoginComponent } from './login.component'; export function tokenGetter() { return localStorage.getItem('access_token'); } @NgModule({ declarations: [ AppComponent, LoginComponent ], imports: [ BrowserModule, HttpClientModule, AppRoutingModule, JwtModule.forRoot({ config: { tokenGetter: tokenGetter, allowedDomains: ['localhost:3000', 'jouw-api-domein.nl'], disallowedRoutes: ['http://localhost:3000/api/auth/'] } }) ], providers: [ AuthService, { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true } ], bootstrap: [AppComponent] }) export class AppModule { } ``` ## 7. Route Configuratie ```typescript // app-routing.module.ts import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { AuthGuard } from './auth.guard'; import { LoginComponent } from './login.component'; import { DashboardComponent } from './dashboard.component'; import { ProfileComponent } from './profile.component'; const routes: Routes = [ { path: 'login', component: LoginComponent }, { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }, { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] }, { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule), canActivate: [AuthGuard], data: { expectedRole: 'admin' } }, { path: '', redirectTo: '/dashboard', pathMatch: 'full' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } ``` ## 8. Sessie Beheer en Beveiliging ### Token Vernieuwing ```typescript // auth.service.ts - toevoeging refreshToken(): Observable<string> { return this.http.post<string>('/api/auth/refresh', {}) .pipe( tap(newToken => { this.storeToken(newToken); }) ); } // Automatische token vernieuwing startTokenRefreshTimer(): void { const token = this.getToken(); if (token) { const expires = this.jwtHelper.getTokenExpirationDate(token); const timeout = expires.getTime() - Date.now() - (60 * 1000); // 1 minuut voor verlopen setTimeout(() => { this.refreshToken().subscribe(); }, timeout); } } ``` ### Beveiligingsmaatregelen 1. **HTTPS**: Gebruik altijd HTTPS in productie 2. **HttpOnly Cookies**: Overweeg HttpOnly cookies voor extra beveiliging 3. **CORS**: Configureer CORS correct op je backend 4. **Token Expiration**: Stel korte expiratie tijden in (bijv. 15-30 minuten) 5. **Refresh Tokens**: Implementeer refresh tokens voor betere UX ## 9. Gebruik in Components ```typescript // dashboard.component.ts import { Component, OnInit } from '@angular/core'; import { AuthService } from '../auth.service'; @Component({ selector: 'app-dashboard', template: ` <h1>Welkom, {{ user?.name }}!</h1> <button (click)="logout()">Uitloggen</button> ` }) export class DashboardComponent implements OnInit { user: any; constructor(private authService: AuthService) {} ngOnInit(): void { this.user = this.authService.getCurrentUser(); } logout(): void { this.authService.logout(); } } ``` Dit systeem biedt een robuuste authenticatielaag voor je Angular applicatie met JWT. Het bevat alle essentiële functionaliteit voor gebruikerslogin, routebescherming en sessiebeheer.