Обновление JWT в Angular 17

Мой бэкенд - это Django restframework. Когда я предоставляю свои учетные данные, он выдает мне токены, которые состоят из refresh и access tokens. В моем бэкенде время действия access_tokens составляет 2 минуты (только для тестирования, но будет увеличиваться до 15 минут), а время действия refresh_tokens составляет 15 дней. Когда срок действия access_token истекает, я отправляю refresh_token для получения нового access_token (только предоставляет access_token).

На front_end (Angular 17) я реализовал получение новых access_tokens, вместо получения новых токенов я получаю logout через 2 минуты.

Я новичок в Angular. Я пытался отладить, но не смог найти решение. Я размещаю свой класс сервиса и перехватчик.

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

  const auth_service = inject(AuthService);

  const accessToken = auth_service.getAccessToken();
  let authReq = req;

  if (accessToken)
  {
    authReq = req.clone({
      setHeaders: {
        Authorization: `Bearer ${accessToken}`
      }
    });
  }

  return next(authReq).pipe(
    catchError((error: HttpErrorResponse) => {
      if (error.status === 401 && error.error.code === 'token_not_valid') {
        console.log('Token expired, attempting to refresh...');
        // Token expired, attempt to refresh
        return auth_service.refreshTokenRequest().pipe(
          switchMap(() => {
            const newAccessToken = auth_service.getAccessToken();
            if (newAccessToken) {
              console.log('New access token received');
              authReq = req.clone({
                setHeaders: {
                  Authorization: `Bearer ${newAccessToken}`
                }
              });
            }
            return next(authReq);
          }),
          catchError((err) => {
            console.error('Token refresh failed:', err);
            auth_service.logout();
            return throwError(() => err);
          })
        );
      }
      return throwError(() => error);
    })
  );

};

и мой класс обслуживания -

export class AuthService {

  constructor() { }

  http = inject(HttpClient);
  router = inject(Router);

  private apiUrl = 'http://localhost:8000/api/v1/';
  private jwtHelper = new JwtHelperService();
  private accessToken: string | null = null;
  private refreshToken: string | null = null;
  private isAuthenticatedSubject = new BehaviorSubject<boolean>(false);
  storeJWTToken(token: any): void
  {
    localStorage.setItem('access_token', token.access);
    localStorage.setItem('refresh_token', token.refresh);
    if (token.access)
      this.accessToken = token.access;
    if (token.refresh)
      this.refreshToken = token.refresh;
    this.isAuthenticatedSubject.next(true);
  }

  login(user: User) : Observable<any>
  {
    return this.http.post<any>(this.apiUrl + 'login/', user)
    .pipe(tap(response => {
      console.log('tokens:', response.access);
      this.storeJWTToken(response);
    }))
    ;
  }

  logout(): void {
    try 
    {
      localStorage.removeItem('access_token');
      localStorage.removeItem('refresh_token');
      this.isAuthenticatedSubject.next(false);
      this.router.navigate(['/login']);
    } 
    catch (error) 
    {
      console.error('Error while logging out:', error);
    }
  }

  isLoggedIn()
  {
    const Token = this.getAccessToken();
    return Token ? !this.jwtHelper.isTokenExpired(Token) : false;
  }

  isAuthenticated() : boolean
  {
    const token = this.accessToken || localStorage.getItem('access_token');
    return token ? !this.jwtHelper.isTokenExpired(token) : false;
  }

  getAccessToken() : string | null
  {
    return this.accessToken || localStorage.getItem('access_token');
  }

  refreshTokenRequest() : Observable<any>
  {
    const refreshToken = this.refreshToken || localStorage.getItem('refresh_token');
    if (!refreshToken)
      return throwError(() => new Error('No refresh token found'));
    return this.http.post<any>(this.apiUrl + 'login/refresh/', {refresh: refreshToken})
    .pipe(tap(response => {
      this.accessToken = response.access;
      if (this.accessToken)
        localStorage.setItem('access_token', this.accessToken);
    })
    );
  }
}

Я пробовал это, но так и не смог найти проблему.

и мой файл app.config.ts имеет следующий вид

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideAnimationsAsync(),
    provideHttpClient(
      withXsrfConfiguration({
        cookieName: 'csrftoken',
        headerName: 'X-CSRFToken',
      }),
      withInterceptors([authInterceptor]),
    ),
    importProvidersFrom([
      JwtModule.forRoot({
        config: {
          tokenGetter: () => localStorage.getItem('access_token')
        }
      })
    ]),
  ]
};
Вернуться на верх