Switch to localStorage for JWT handling and simplify case transformation logic in LoginComponent. Update app.config.ts and related services to align with the new token management method. Mark JwtClaims interface as exported.

This commit is contained in:
akastijn 2025-07-06 19:10:17 +02:00
parent 54e747118c
commit 04310e1cce
6 changed files with 28 additions and 43 deletions

View File

@ -1,26 +1,29 @@
import {ApplicationConfig, provideZoneChangeDetection} from '@angular/core';
import {ApplicationConfig, importProvidersFrom, provideZoneChangeDetection} from '@angular/core';
import {provideRouter} from '@angular/router';
import {JwtHelperService, JwtModule} from '@auth0/angular-jwt';
import {CookieService} from 'ngx-cookie-service';
import {routes} from './app.routes';
// Function to get the JWT token from cookies
export function jwtTokenGetter() {
const cookieService = new CookieService(document, null);
return cookieService.check('jwt') ? cookieService.get('jwt') : null;
return localStorage.getItem('jwt');
}
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({eventCoalescing: true}),
provideRouter(routes),
{ provide: CookieService, useClass: CookieService },
{ provide: JwtHelperService, useClass: JwtHelperService },
{ provide: JwtModule, useValue: JwtModule.forRoot({
config: {
tokenGetter: jwtTokenGetter
}
})}
CookieService,
{
provide: JwtHelperService,
useValue: new JwtHelperService()
},
importProvidersFrom(
JwtModule.forRoot({
config: {
tokenGetter: jwtTokenGetter
}
})
)
]
};

View File

@ -6,6 +6,7 @@ import {CommonModule, NgOptimizedImage} from '@angular/common';
import {HeaderComponent} from '@header/header.component';
import {CopyIpComponent} from '@shared-components/copy-ip/copy-ip.component';
import {RouterLink} from '@angular/router';
import {JwtHelperService} from '@auth0/angular-jwt';
@Component({
standalone: true,
@ -16,6 +17,9 @@ import {RouterLink} from '@angular/router';
RouterLink,
NgOptimizedImage
],
providers: [
{provide: JwtHelperService, useFactory: () => new JwtHelperService()}
],
selector: 'app-home',
templateUrl: './home.component.html',
styleUrl: './home.component.scss'

View File

@ -1,10 +1,10 @@
import {Injectable} from '@angular/core';
import {LoginService} from '@api';
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';
import {JwtClaims} from '@custom-types/jwt_interface'
@Injectable({
providedIn: 'root'
@ -18,7 +18,6 @@ export class AuthService {
constructor(
private loginService: LoginService,
private cookieService: CookieService,
private snackBar: MatSnackBar,
private jwtHelper: JwtHelperService
) {
@ -46,7 +45,7 @@ export class AuthService {
* Log the user out by removing the JWT
*/
public logout(): void {
this.cookieService.delete('jwt', '/');
localStorage.removeItem('jwt');
this.isAuthenticatedSubject.next(false);
this.userClaimsSubject.next(null);
}
@ -76,25 +75,20 @@ export class AuthService {
}
/**
* Get the JWT from cookies
* Get the JWT from localStorage
*/
public getJwt(): string | null {
return this.cookieService.check('jwt') ? this.cookieService.get('jwt') : null;
return localStorage.getItem('jwt');
}
/**
* Save the JWT to cookies
* Save the JWT to localStorage
*/
private saveJwt(jwt: string): void {
this.cookieService.set('jwt', jwt, {
path: '/',
secure: true,
sameSite: 'Strict'
});
localStorage.setItem('jwt', jwt);
const claims = this.extractJwtClaims(jwt);
this.userClaimsSubject.next(claims);
}
/**

View File

@ -3,7 +3,7 @@
<form [formGroup]="loginForm">
<mat-form-field appearance="fill" style="width: 100%">
<mat-label>Enter your code</mat-label>
<input matInput formControlName="code" type="text" (keydown)="onKeyDown($event)">
<input matInput formControlName="code" type="text" (keyup)="onKeyUp()">
<mat-error *ngIf="loginForm.get('code')?.errors?.['required']">
Code is required
</mat-error>

View File

@ -65,23 +65,7 @@ export class LoginDialogComponent {
});
}
onKeyDown(event: KeyboardEvent): void {
if (event.key.length === 1 && event.key >= 'a' && event.key <= 'z') {
event.preventDefault();
const input = event.target as HTMLInputElement;
const start = input.selectionStart || 0;
const end = input.selectionEnd || 0;
const value = this.loginForm.get('code')?.value || '';
const newValue =
value.substring(0, start) +
event.key.toUpperCase() +
value.substring(end);
this.loginForm.get('code')?.setValue(newValue);
setTimeout(() => {
input.setSelectionRange(start + 1, start + 1);
});
}
onKeyUp(): void {
this.loginForm.patchValue({'code': this.loginForm.get('code')?.value.toUpperCase()})
}
}

View File

@ -1,4 +1,4 @@
interface JwtClaims {
export interface JwtClaims {
iss?: string;
sub?: string;
iat?: number;