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...

Suren Srapyan
  • 66,568
  • 14
  • 114
  • 112
ValRob
  • 2,584
  • 7
  • 32
  • 40

10 Answers10

64

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
    ]
elDuderino
  • 996
  • 1
  • 7
  • 12
26

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

Suren Srapyan
  • 66,568
  • 14
  • 114
  • 112
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/"],
      },
    }),
Harrish Selvarajah
  • 1,763
  • 12
  • 11
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

Pingu510
  • 43
  • 4
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.

JoSSte
  • 2,953
  • 6
  • 34
  • 54
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); 
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);
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';
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

-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';
Abdes
  • 926
  • 1
  • 15
  • 27