NullInjectorError: No provider for JwtHelperService
Asked Answered
M

10

33

I'm in Angular 5.

First: npm install @auth0/angular-jwt --save

Then I import it: import { JwtHelperService } from '@auth0/angular-jwt';

This is my authentication service:

import { JwtHelperService } from '@auth0/angular-jwt';

@Injectable()
export class AuthService {

  constructor(public jwtHelper: JwtHelperService) { }

  public isAuthenticated(): boolean {
    console.log (localStorage['token']);
    const token = localStorage.getItem('token');
    // Check wheter the token is expired and return true or false
    return !this.jwtHelper.isTokenExpired(token);
  }
}

And this is my Guard service

export class GuardService implements CanActivate {

  constructor(public auth: AuthService, public router: Router) {}

  canActivate(): boolean {
    if (!this.auth.isAuthenticated()){
        console.log ('bye');
        this.router.navigate(['/login']);
        return false;
    }
    console.log ('Welcome');
    return true;
  }

}

There is a token in the localstorage:

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImFjMTUyNzZhZjA2MjU1YTdlMDM0MmQ5ODg4N2M1ZmI2ZWNmM2RlNGUyNjhmYTc4MTliODRhOTVmMmJiNGZiMTliMDFkNjBhNWRlNjhlN2VlIn0.eyJhdWQiOiJmMDExY2M1OC00MGNlLTQzYTktOGY3MS04NDI0OTRlM2E5OTciLCJqdGkiOiJhYzE1Mjc2YWYwNjI1NWE3ZTAzNDJkOTg4ODdjNWZiNmVjZjNkZTRlMjY4ZmE3ODE5Yjg0YTk1ZjJiYjRmYjE5YjAxZDYwYTVkZTY4ZTdlZSIsImlhdCI6MTUyMzI5NzkzNSwibmJmIjoxNTIzMjk3OTM1LCJleHAiOjE1MjMyOTgyMzUsInN1YiI6IjIiLCJzY29wZXMiOlsiYXV0aGVudGljYXRlZCIsImFuZ3VkcnUiXX0.RNY2Yb9xiJDcER4rtHEAYMmoLyvPYij-upZc97q-mSgICKE6_xWih_IBjY4cHQXkkiRyCXaqCfwfMM4YWVjv7bsMlLN5bWlH0JTeYoYf2gENLBIG51NwGpU3iAl8KG_51ljZKbs3RE_ULDbphM1NG8BhobVQ5RlObWzejrkPcMHqlGJaMOMLQuXC1iBR2jI9tlfiP4RD4FUUsRkUEUJ5PSIRl34jWoTv31SSf1bkv43q3YeKTfk6pXZ5Ft_eV8G871KkmQSHANAn26A5ujj2FOh-uCV_VNJ97RuTQ6J4NP2YB-mMaWYpZ1xF-4ndqafRGFXJ_8euBO4cA36zvP3B7g

And this is the error:

ERROR Error: Uncaught (in promise): Error: StaticInjectorError(AppModule)[AuthService -> JwtHelperService]: 
  StaticInjectorError(Platform: core)[AuthService -> JwtHelperService]: 
    NullInjectorError: No provider for JwtHelperService!
Error: StaticInjectorError(AppModule)[AuthService -> JwtHelperService]: 
  StaticInjectorError(Platform: core)[AuthService -> JwtHelperService]: 
    NullInjectorError: No provider for JwtHelperService!
    at _NullInjector.get (core.js:1002)
    at resolveToken (core.js:1300)
    at tryResolveToken (core.js:1242)
    at StaticInjector.get (core.js:1110)
    at resolveToken (core.js:1300)
    at tryResolveToken (core.js:1242)
    at StaticInjector.get (core.js:1110)
    at resolveNgModuleDep (core.js:10854)
    at _createClass (core.js:10891)
    at _createProviderInstance$1 (core.js:10865)
    at _NullInjector.get (core.js:1002)
    at resolveToken (core.js:1300)
    at tryResolveToken (core.js:1242)
    at StaticInjector.get (core.js:1110)
    at resolveToken (core.js:1300)
    at tryResolveToken (core.js:1242)
    at StaticInjector.get (core.js:1110)
    at resolveNgModuleDep (core.js:10854)
    at _createClass (core.js:10891)
    at _createProviderInstance$1 (core.js:10865)
    at resolvePromise (zone.js:814)
    at resolvePromise (zone.js:771)
    at eval (zone.js:873)
    at ZoneDelegate.invokeTask (zone.js:421)
    at Object.onInvokeTask (core.js:4740)
    at ZoneDelegate.invokeTask (zone.js:420)
    at Zone.runTask (zone.js:188)
    at drainMicroTaskQueue (zone.js:595)

Also, it shows me the route, but without the array from the service...

Mulligatawny answered 9/4, 2018 at 18:21 Comment(0)
P
27

You need to use JwtModule provided by the @auth0/angular-jwt, which will add JwtHelperService to the providers, or you need to add it manually to the modules provider.

Something like

const JWT_Module_Options: JwtModuleOptions = {
    config: {
        tokenGetter: yourTokenGetter,
        whitelistedDomains: yourWhitelistedDomains
    }
};

@NgModule({
    imports: [
        JwtModule.forRoot(JWT_Module_Options)
    ],
...

Fore more see Documentation

Pitchford answered 9/4, 2018 at 18:24 Comment(1)
Yes, it is preferable to use in the top modulePitchford
C
66

A little late to the party, but I ran into the same issue trying to follow the standalone docs and what it doesn't cover is the need to import the options InjectionToken which is referenced in the constructor of the service:

import { JwtHelperService, JWT_OPTIONS  } from '@auth0/angular-jwt';

...

providers: [
        { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
        JwtHelperService
    ]
Cultivation answered 13/5, 2019 at 20:41 Comment(2)
are these going into app.module.ts?Horseradish
I think this should be the correct answer.Phytohormone
P
27

You need to use JwtModule provided by the @auth0/angular-jwt, which will add JwtHelperService to the providers, or you need to add it manually to the modules provider.

Something like

const JWT_Module_Options: JwtModuleOptions = {
    config: {
        tokenGetter: yourTokenGetter,
        whitelistedDomains: yourWhitelistedDomains
    }
};

@NgModule({
    imports: [
        JwtModule.forRoot(JWT_Module_Options)
    ],
...

Fore more see Documentation

Pitchford answered 9/4, 2018 at 18:24 Comment(1)
Yes, it is preferable to use in the top modulePitchford
M
4

This problem occurs because you have not added JWTmodule to imports in app.module.ts

export function tokenGetter() {
  return localStorage.getItem("access_token");
}

JwtModule.forRoot({
      config: {
        tokenGetter: tokenGetter,
        allowedDomains: ["example.com"],
        disallowedRoutes: ["http://example.com/examplebadroute/"],
      },
    }),
Minna answered 21/8, 2020 at 19:13 Comment(0)
A
3

For future reference, if all you want to use JwtHelper for is decoding, like in this case checking if the token is expired, then you can use this.

import { JwtHelperService } from '@auth0/angular-jwt';

const jwtHelper = new JwtHelperService();

@Injectable()
export class AuthService {
    public isAuthenticated(): boolean {
    const token = localStorage.getItem('token');

    // Check if the token is expired and return true or false
    return !this.jwtHelper.isTokenExpired(token);
}

Source: Documentation

Akkad answered 14/3, 2019 at 13:57 Comment(0)
F
3

I battled with this issue as well. I found a workaround:

Test configuration

In your modulename.spec.ts make sure that you configure a provider for the JwtHelperService (In my case it was AuthGuard.spec.ts):


import { TestBed, inject, waitForAsync } from '@angular/core/testing';
import { RouterTestingModule } from "@angular/router/testing";
import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing';
import { JwtModule, JwtHelperService } from '@auth0/angular-jwt';

import { AuthGuard } from './auth.guard';

let jwtHelper: JwtHelperService;
const testBedConfiguration = {
  imports: [
    RouterTestingModule.withRoutes([]),
    HttpClientTestingModule,
    JwtModule.forRoot({ // for JwtHelperService
      config: {
        tokenGetter: () => {
          return '';
        }
      }
    })
  ],
  providers: [
    AuthGuard,
    JwtHelperService
  ]
}

describe('AuthGuard', () => {
  beforeEach(() => {
    TestBed.configureTestingModule(testBedConfiguration);
    jwtHelper = TestBed.get(JwtHelperService);
  });

  it('should ...', inject([AuthGuard], (guard: AuthGuard) => {
    expect(guard).toBeTruthy();
  }));
});

This solved my issue, but since my implementation was in my auth service which is used by my authguard for the routes, I have to include that config in every single page I have protected by the authguard.

Francyne answered 26/12, 2020 at 13:56 Comment(0)
P
2

If you used @auth0/angular-jwt to get the jwt assistance and used dependency injection to access the module it is necessary to import jwt module to the app.module.ts or what ever the module you used.moreover you have more privileges to configure your module importers with disallowed domains, allowed domains , header name, custom factory functions etc.

import { JwtModule } from "@auth0/angular-jwt";
import { HttpClientModule } from "@angular/common/http";

export function tokenGetter() {
  return localStorage.getItem("access_token");
}

@NgModule({
  bootstrap: [AppComponent],
  imports: [
    // ...
    HttpClientModule,
    JwtModule.forRoot({
      config: {
       tokenGetter: tokenGetter,
      allowedDomains: ["localhost:3001", "foo.com", "bar.com"]
      },
    }),
  ],
})
export class AppModule {}

if you don't want to inject it, you can instantiate.

import { JwtHelperService } from "@auth0/angular-jwt";

const helper = new JwtHelperService();

const decodedToken = helper.decodeToken(myRawToken);
const expirationDate = helper.getTokenExpirationDate(myRawToken);
const isExpired = helper.isTokenExpired(myRawToken); 
Paronomasia answered 10/11, 2020 at 14:54 Comment(0)
C
1

The simplest solution which worked for me is declaring constant variable type of "JwtHelperService" instead of declaring it in a constructor.

 const helper = new JwtHelperService ();

Now use helper services with helper constant

 return !helper.isTokenExpired(token);
Ciliolate answered 2/7, 2020 at 14:25 Comment(0)
R
1

In the ngModule add in providers this :

providers: [JwtHelperService,{ provide: JWT_OPTIONS, useValue: JWT_OPTIONS },],

so this will be imported :

import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';

in your component just import like this :

import { JwtHelperService} from '@auth0/angular-jwt';
Riposte answered 18/3, 2023 at 20:4 Comment(0)
E
0
import { JwtModule, JwtHelperService } from '@auth0/angular-jwt';

public jwtHelper: JwtHelperService = new JwtHelperService();

constructor(
private http: Http,
) { }
     decodeToken() {
         const token = localStorage.getItem('token');
         return this.jwtHelper.decodeToken(token);
     }

this fixed my problem https://github.com/auth0/angular2-jwt/issues/482#issuecomment-569251938

Eldoraeldorado answered 18/5, 2022 at 13:57 Comment(0)
F
-1

I fixed this issues by changing my import from :

import { JwtHelperService } from '@auth0/angular-jwt';

to

import { JwtHelperService } from '@auth0/angular-jwt/src/jwthelper.service';
Frippery answered 13/11, 2019 at 8:18 Comment(1)
This is a non standard and so not recommended practiceIncreate

© 2022 - 2024 — McMap. All rights reserved.