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

