1. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

Angular sending access_token in headers when I try to refresh token

Discussão em 'Angular' iniciado por PawelC, Outubro 17, 2024 às 07:13.

  1. PawelC

    PawelC Guest

    I'm writing an application in PHP as a backend, for now an authorization module and I have done a login in Angular, which works correctly. Unfortunately I have a problem with the implementation of refresh_token on the Angular side.

    I have 2 interceptors: JWTInterceptor responsible for adding token to all requests, it works well.

    import {
    HttpEvent,
    HttpHandler, HttpHandlerFn,
    HttpInterceptorFn,
    HttpRequest,
    } from '@angular/common/http';
    import {catchError, Observable, switchMap, throwError} from "rxjs";
    import {inject} from "@angular/core";
    import {AuthService} from "./services/auth.service";
    import {Router} from "@angular/router";

    export const JwtInterceptor: HttpInterceptorFn = (req, next) => {

    let authToken = localStorage.getItem('access_token');
    console.log("JwtInterceptor")
    if (authToken) {
    let authReq = req.clone({
    setHeaders: {
    Authorization: `Bearer ${authToken}`,
    },
    });
    return next(authReq);
    } else {
    return next(req);
    }
    }


    Second interceptor is tokenInterceptor who is responsible for catching expired JWT Token. Unfortunately he doesn't work well. The problem is that under the endpoint with the refresh token, it also sends the expired access_token in the header, so the API returns the JWT Expired error instead of refreshing the token. Below is the interceptor code:

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

    export const tokenInterceptor: HttpInterceptorFn = (req, next) => {
    console.log("TokenInterceptor")
    let authToken = localStorage.getItem('token');
    let authService = inject(AuthService);

    if (authToken) {
    req = req.clone({
    setHeaders: {
    Authorization: `Bearer ${authToken}`,
    },
    });
    }
    return next(req).pipe(
    catchError((errorData: HttpErrorResponse) => {

    if(errorData.status == 401) {
    console.error("Token Interceptor Error to 401");

    return authService.refreshToken().pipe(
    switchMap(() => {
    console.error("Refresh token done")
    const newAccessToken = localStorage.getItem('access_token');
    // Retry the original request with the new access token
    req = req.clone({
    setHeaders: {
    Authorization: `Bearer ${newAccessToken}`,
    },
    });
    return next(req);
    }),
    catchError((error) => {
    // Handle refresh token error (e.g., redirect to login page)
    console.error('Error handling expired access token:', error);
    return throwError(error);
    })
    )
    }
    throw errorData;
    })
    );
    };


    It look like this:

    1. Send request to backend

    [​IMG]

    As you can see, Authorization token is added to headers.

    1. In body I have valid refresh_token

    [​IMG]

    1. Backend return mi error "Expired JWT Token"

    [​IMG]

    I tried to reproduce this situation using postman by hitting the API with refresh_token and access_token in the header and I get the same error [​IMG]

    But when I send refresh_token, but without access_token added in the header, my token is refreshed correctly. [​IMG]

    So the question is, what do I have wrong in the code on the angular side that it attaches access_token. How do I fix this error? Honestly, nothing comes to mind :(

    In console this look like this [​IMG]

    Continue reading...

Compartilhe esta Página