Refresh token not working after token expiration in Angular 18

Discussão em 'Angular' iniciado por PawelC, Outubro 15, 2024.

  1. PawelC

    PawelC Guest

    I wrote a backend in PHP for my application, now I'm trying to write a frontend in Angular, but I have a problem with the refresh token, i.e. when the token expires, it doesn't refresh, but takes me straight to the login screen. It looks like catchError doesn't activate My authInterceptor

    import {HttpErrorResponse, HttpInterceptorFn, HttpResponse} from '@angular/common/http';
    import {catchError, throwError} from "rxjs";
    import {inject} from "@angular/core";
    import {AuthService} from "./services/auth.service";
    import Swal from "sweetalert2";
    import {Router} from "@angular/router";

    export const authInterceptor: HttpInterceptorFn = (req, next) => {
    let isRefreshing = false;

    let authToken = localStorage.getItem('token');
    let authService = inject(AuthService);
    let router = inject(Router);

    const authReq = req.clone({
    headers: req.headers.set("Authorization", `Bearer ${authToken}`)
    });

    if (authToken) {
    console.log("Auth token");
    return next(authReq).pipe(

    catchError((errorData: HttpErrorResponse) => {
    if (errorData.status === 401) {
    let refreshToken = localStorage.getItem('refresh_token');
    if (refreshToken) {
    authService.refreshToken().subscribe({

    next: (data: any) => {
    console.log("Refresh token");
    localStorage.clear();
    localStorage.setItem('token', data.token);
    localStorage.setItem('refresh_token', data.refresh_token);
    localStorage.setItem('refresh_token_expiration', data.refresh_token_expiration);

    const newAuthReq = req.clone({
    headers: req.headers.set("Authorization", `Bearer ${data.token}`)
    });
    return next(newAuthReq);
    },
    error: (errorData: HttpErrorResponse) => {
    if (errorData.status === 403) {
    console.log("Error 403");
    localStorage.clear();
    router.navigate(['login']);
    }
    }
    })
    } else {
    console.log("Missing token");
    localStorage.clear();
    router.navigate(['login']);
    }
    }
    return throwError(errorData)
    }));
    } else {
    return next(req);
    }
    }


    authService.ts

    import {Injectable} from '@angular/core';
    import {HttpClient, HttpHeaders} from "@angular/common/http";
    import {environment} from "../../environments/environment.development";
    import Swal from "sweetalert2";
    import {Router} from "@angular/router";
    import {FormGroup} from "@angular/forms";
    import {JwtHelperService} from "@auth0/angular-jwt";

    @Injectable({
    providedIn: 'root'
    })
    export class AuthService {

    constructor(
    private http: HttpClient,
    private router: Router,
    public jwtHelper: JwtHelperService) {
    }

    login(loginForm: FormGroup) {
    this.http.post(environment.apiUrl + '/login_check', loginForm.value).subscribe({
    next: (data: any) => {
    localStorage.setItem('token', data.token);
    localStorage.setItem('refresh_token', data.refresh_token);
    localStorage.setItem('refresh_token_expiration', data.refresh_token_expiration);

    this.router.navigate(["/"])
    },
    error: (err) => {
    Swal.fire({
    title: 'Authorization error',
    text: err.error.message,
    icon: 'error'
    })
    }
    })
    }

    logout(): void {
    localStorage.clear()
    this.router.navigate(['/login'])
    }

    isAuthenticatedUser(): boolean {
    let token = localStorage.getItem("token")

    if (token && !this.jwtHelper.isTokenExpired(token)) {
    return true;
    }
    localStorage.clear();
    this.router.navigate(['/login'])
    return false;
    }

    refreshToken() {
    let refresh_token = localStorage.getItem("refresh_token");
    return this.http.post(environment.apiUrl + '/api/token/refresh', refresh_token);
    }
    }


    authGuard.ts

    import {CanActivateFn, Router} from '@angular/router';
    import {AuthService} from "../services/auth.service";
    import {inject} from "@angular/core";

    export const authGuard: CanActivateFn = (route, state) => {

    const authService = inject(AuthService);

    return authService.isAuthenticatedUser();
    };


    Additionally, in the HomeComponent component, I have added a simple http.get to test the interceptor

    import {Component} from '@angular/core';
    import {RouterLink, RouterOutlet} from "@angular/router";
    import {HttpClient} from "@angular/common/http";

    @Component({
    selector: 'app-home',
    standalone: true,
    imports: [
    RouterLink,
    RouterOutlet
    ],
    templateUrl: './home.component.html',
    styleUrl: './home.component.css'
    })
    export class HomeComponent {

    constructor(private _http: HttpClient) {

    _http.get('https://jsonplaceholder.typicode.com/posts', {observe: 'response'}).subscribe(res => {
    console.log('Response status:', res.status);
    })
    }
    }


    In the console it looks like this: the request is sent when I refresh, then when the token expires, I am immediately logged out without refreshing the token.

    I honestly don't know what the problem might be, because I'm just learning Angular.

    [​IMG]

    Continue reading...

Compartilhe esta Página