2

I am working with Angular 13, attempting to add a JWT to headers to access a restricted route on the backend. Upon backend inspection JwtInterceptor does not appear to modify the HTTP request headers. I've only included HttpClientModule once in my project, in the root AppModule. I've appended a pipe function with error catching to my next object (inside of interceptor) in an effort to debug as suggested by someone with a similar issue on SO to no avail, removed pipe funct for brevity.

I've gone as basic as console.log'ing within the file but there was no output to account for it so I suspect the interceptor isn't firing at all.

I've worked with interceptors before and haven't had this issue so I'm stumped. The only difference here is that I'm working with an Angular PWA, if I understand correctly a service worker is not supposed to hinder the behavior of an interceptor? I understood that a POST request would fall under a "cache busting" event?

Maybe the error is in the implementation of the PWA? I did follow the docs in this case.

Attached are the App Module, Jwtinterceptor and "Barrel" of HttpInterceptors, I'm planning on adding more interceptors to project so I followed the docs suggestion and created the Barrel.

TL;DR
My HttpInterceptor (JwtInterceptor) does not appear to be firing at all. This implementation has worked for me in past projects, only difference is this project is a PWA. Not sure if it's a conflict or quirk with PWA implementation. HttpClientModule is included only once in project.

app.module.ts

//Angular level imports
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppRoutingModule } from './app-routing.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

//App level components
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { HeaderComponent } from './header/header.component';
import { AngularMaterialModule } from './_material/material.module';
import { UploadDirective } from './directives/upload.directive';
import { LoginComponent } from './login/login.component';
import { RegisterComponent } from './register/register.component';
import { ThanksComponent } from './thanks/thanks.component';
import { PhotoAlbumsComponent } from './photo-albums/photo-albums.component';
import { DialogComponent } from './dialog/dialog.component';
import { AlbumComponent } from './album/album.component';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
import { ForgotPasswordComponent } from './forgot-password/forgot-password.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
import { ThanksBotDownloadComponent } from './thanks-bot-download/thanks-bot-download.component';
import { ErrorBotDownloadComponent } from './error-bot-download/error-bot-download.component';
import { RouterModule } from '@angular/router';
import { httpInterceptorProviders } from './_interceptors/index';

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    HeaderComponent,
    UploadDirective,
    LoginComponent,
    RegisterComponent,
    ThanksComponent,
    PhotoAlbumsComponent,
    AlbumComponent,
    DialogComponent,
    ForgotPasswordComponent,
    ResetPasswordComponent,
    ThanksBotDownloadComponent,
    ErrorBotDownloadComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    FormsModule,
    ReactiveFormsModule,
    AngularMaterialModule,
    ServiceWorkerModule.register('ngsw-worker.js', {
      enabled: environment.production,
      // Register the ServiceWorker as soon as the app is stable
      // or after 30 seconds (whichever comes first).
      registrationStrategy: 'registerWhenStable:30000',
    }),
    HttpClientModule,
    RouterModule,
  ],
  providers: [httpInterceptorProviders],
  bootstrap: [AppComponent],
})
export class AppModule {}

jwt.interceptor.ts

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor,
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { environment } from '@environments/environment';
import { AccountService } from '@app/_services/account.service';


@Injectable()
export class JwtInterceptor implements HttpInterceptor {
  constructor(private accountService: AccountService) {}

  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    // add auth header with jwt if user is logged in and request is to the api url
    //console.log("JWT Interceptor");
    const user = this.accountService.currentUserValue;
    const isLoggedIn = user && user.jwt;
    const isApiUrl = request.url.startsWith(environment.apiUrl);
    if (isLoggedIn && isApiUrl) {
      request = request.clone({
        setHeaders: {
          Authorization: `Bearer ${user.jwt}`,
        },
      });
    }

    return next.handle(request);
  }
}

index.ts "Barrel" file

/* "Barrel" of Http interceptors */
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { JwtInterceptor } from './jwt.interceptor';

/* Http interceptor providers in outside-in order */
export const httpInterceptorProviders = [
  { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
];

Post request Headers Request Headers on backend

5
  • Hi. httpInterceptorProviders is array rigth? [...httpInterceptorProviders] try this Commented Jan 3, 2022 at 21:33
  • @MohammadBabaei That's correct httpInterceptorProviders is an array. Prepend the spread operator to the providers array in my AppModule? I tried it in case that's what you mean and it's still failing. Apologies if that's not what you meant, perhaps you can please clarify if so. Commented Jan 4, 2022 at 0:53
  • Just to confirm, you are able to hit the if condition, correct? Commented Jan 4, 2022 at 4:16
  • 1
    @DerrickRose As of now, I do not believe I'm hitting the if condition. I did have a console.log("JWT Interceptor"); as an informal way to check but no log whenever I send requests over the wire. Thanks for your response, if I can get the darn file to even register I will accept, as it appears it will work and is the most comprehensive response to date. Commented Jan 4, 2022 at 5:11
  • @DerrickRose Following up since I was browsing SO. Accepted your response. Posted my solution below yours, thanks for the help. Commented Mar 4, 2022 at 8:49

2 Answers 2

2

Instead of setHeaders try headers.

request = req.clone({
    headers: req.headers.append('Authorization', `Bearer ${user.jwt}`)
});

Though it seems this issue is caused by your condition not being met.

Sign up to request clarification or add additional context in comments.

Comments

2

Thanks to the people who helped.

The issue had something to do with turning my app into a PWA. The service worker was affecting my token interceptor. I re-did my app without a PWA and is working as expected. So do be careful if your interceptors stop working post service worker implementation, it may not actually be your interceptor.

I would suggest to anyone who has a working app that is interested in turning it into a PWA to read the docs but follow a more comprehensive tutorial because I do feel the Angular docs for more advanced topics are written in a vacuum and lack some context.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.