Add JWT support for authentication handling

Integrate `@auth0/angular-jwt` for Token management. Update `app.config.ts` with `JwtModule` setup and token getter from cookies. Enhance `AuthService` to include token handling, fake login, and JWT validation using `JwtHelperService`. Introduce `JwtClaims` interface for structured token claims.
This commit is contained in:
2025-07-04 22:31:41 +02:00
parent dfea91d8ca
commit f0faa63ca7
5 changed files with 48 additions and 15 deletions
+19 -13
View File
@@ -4,6 +4,7 @@ import {CookieService} from 'ngx-cookie-service';
import {BehaviorSubject, Observable, throwError} from 'rxjs';
import {catchError, tap} from 'rxjs/operators';
import {MatSnackBar} from '@angular/material/snack-bar';
import {JwtHelperService} from '@auth0/angular-jwt';
@Injectable({
providedIn: 'root'
@@ -12,13 +13,14 @@ export class AuthService {
private isAuthenticatedSubject = new BehaviorSubject<boolean>(false);
public isAuthenticated$ = this.isAuthenticatedSubject.asObservable();
private userClaimsSubject = new BehaviorSubject<any>(null);
private userClaimsSubject = new BehaviorSubject<JwtClaims | null>(null);
public userClaims$ = this.userClaimsSubject.asObservable();
constructor(
private loginService: LoginService,
private cookieService: CookieService,
private snackBar: MatSnackBar
private snackBar: MatSnackBar,
private jwtHelper: JwtHelperService
) {
// Check if user is already logged in on service initialization
this.checkAuthStatus();
@@ -30,7 +32,7 @@ export class AuthService {
public login(code: string): Observable<any> {
return this.loginService.login(code).pipe(
tap(jwt => {
this.saveJwt(jwt as JsonWebKey);
this.saveJwt(jwt);
this.isAuthenticatedSubject.next(true);
}),
catchError(error => {
@@ -40,6 +42,13 @@ export class AuthService {
);
}
public fakeLogin(): Observable<any> {
const jwt = 'ZXlKaGJHY2lPaUpTVXpJMU5pSjkuZXlKcGMzTWlPaUpoYkhScGRIVmtaWGRsWWlJc0luTjFZaUk2SWpVMVpUUTJZbU16TFRKaE1qa3ROR00xTXkwNE5UQm1MV1JpWkRrME5HUmpOV00xWmlJc0ltVjRjQ0k2TVRjMU5ESTFNREUyTkN3aWFXRjBJam94TnpVeE5qVTRNVFkwTENKaGRYUm9iM0pwZEdsbGN5STZXeUpUUTA5UVJWOTFjMlZ5SWwxOS5iWU5Ba0hjUEp5ektReTl0cjN2RFB2VUNyX0FtQTNNVEtrZmlLV0dzV2M1QTdjR3ZKay1UYmQzdEJzYU1LZjI0ZUotZmtudjEyWFBGaXRXSmdRRVdNYTJvc19EYWkwZm1kT1J3MUlRb2d5bndOamtnWjBnMUJfU1lCMVRpZV9YQXpJTkNJSkNXMHB4YTB5U0dQUWxPaTJjVE1uWjdlRDlHMkI5NW0tcklMNG9NVDJMa3NwSjR2NXNCSlVrclNEaEl2dkQxOUhvWlFNV0VpU3BUbkQxVVhCSC1NVFVBMWhSSUFaZEd1cTVfWmpsQWNpMlpya195c0ZreGZBYVZHRW4zQXlpMFNmMjZhbEFlSGVxaW90M1lvWDR5djYyd0treThaODdkZVdMcWxvUHBzdi1INXNVX1E3dzhMano4cS1Ecl9hMHVRMlF2bDc4Y1RDV1JtTm04dlE=';
this.saveJwt(jwt);
this.isAuthenticatedSubject.next(true);
return undefined as any;
}
/**
* Log the user out by removing the JWT
*/
@@ -56,14 +65,13 @@ export class AuthService {
const jwt = this.getJwt();
if (jwt) {
try {
const claims = this.extractJwtClaims(jwt as JsonWebKey);
// Check if token is expired
const currentTime = Math.floor(Date.now() / 1000);
if (claims.exp && claims.exp < currentTime) {
if (this.jwtHelper.isTokenExpired(jwt)) {
this.logout();
return false;
}
const claims = this.extractJwtClaims(jwt);
this.userClaimsSubject.next(claims);
this.isAuthenticatedSubject.next(true);
return true;
@@ -84,8 +92,8 @@ export class AuthService {
/**
* Save the JWT to cookies
*/
private saveJwt(jwt: JsonWebKey): void {
this.cookieService.set('jwt', jwt.toString(), {
private saveJwt(jwt: string): void {
this.cookieService.set('jwt', jwt, {
path: '/',
secure: true,
sameSite: 'Strict'
@@ -93,16 +101,14 @@ export class AuthService {
const claims = this.extractJwtClaims(jwt);
this.userClaimsSubject.next(claims);
}
/**
* Extract claims from JWT
*/
private extractJwtClaims(jwt: JsonWebKey): any {
const token = jwt.toString();
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
return JSON.parse(window.atob(base64));
private extractJwtClaims(jwt: string): JwtClaims {
return <JwtClaims>this.jwtHelper.decodeToken(jwt);
}
/**