NullInjectorError: No provider for OidcDataService
Asked Answered
S

1

11

I am new to OpenID and Angular, and am trying to make use of the angular-auth-oidc-client package. There are some great examples by damienbod and elanderson, but I can't even seem to get off the starting block.

After installing the package, all I have to do is inject the OidcSecurityService - I don't have to use it even - and I am getting a runtime error:

StaticInjectorError(AppModule)[OidcSecurityService -> OidcDataService]: 
  StaticInjectorError(Platform: core)[OidcSecurityService ->  OidcDataService]: 
    NullInjectorError: No provider for OidcDataService!
...

My natural thought was to import OidcDataService and add it to the providers, but that results in a compiler error:

ERROR in src/app/app.module.ts(3,31): error TS2305: 
  Module '"<...>/auth-test/node_modules/angular-auth-oidc-client/index"' 
    has no exported member 'OidcDataService'.

My Google-fu has uncovered nothing that appears relevant, and it is blocking so early in the process of integrating the package, that I must be making a bad assumption somewhere about how to link everything together. Can anyone see it?

Reproducing

I can reproduce with a minimal project. Create the project with these steps:

ng new auth-test
npm install angular-auth-oidc-client --save

Then add the Oidc services so that app.module.ts looks like this:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { OidcSecurityService } from 'angular-auth-oidc-client';

import { AppComponent } from './app.component';


@NgModule({
  declarations: [ AppComponent ],
  imports: [ BrowserModule ],
  providers: [ OidcSecurityService ],
  bootstrap: [ AppComponent ]
})
export class AppModule {
  constructor(
      private oidcSecurityService: OidcSecurityService
  ) {
    // I would configure my STS Server, etc, if I could just get past this bug.
  }
}

Then just serve it up and view the console for the runtime error.

ng serve
Sulph answered 18/1, 2018 at 21:29 Comment(0)
S
18

OK. I think I see where I went wrong. The samples are good, but they have enough complexity that that I didn't consider that the AuthModule was part of the package. I thought it was something the samples build around the package. The brief example in the angular-auth-oidc-client README set me on the right track

So AuthModule needs to be imported (my larger, real project did), but it also needs a call to AuthModule.forRoot() to be included in the AppModule imports metadata (my larger, real project did not).

So with those updates, app.module.ts now looks like this:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';
import { AuthModule, OidcSecurityService } from 'angular-auth-oidc-client';

import { AppComponent } from './app.component';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    AuthModule.forRoot(),
    RouterModule.forRoot([{path: "", component:AppComponent}])

  ],
  providers: [OidcSecurityService],
  bootstrap: [AppComponent]
})
export class AppModule {
  constructor(
      private oidcSecurityService: OidcSecurityService
  ) {
    // Now I can configure my STS Server, and off I go.
  }
}

And works. Note the addition of the RouterModule, as well, which the AuthModule depends on, and it's .forRoot(), both of which also were in my real project, but needed to be added to this minimal proof-of-concept.

It became apparent to me that there was a hole in my understanding around .forRoot(). In short, we need to make sure that the things the AuthModule provides are provided to the whole rest of the App.

I found this article helpful in filling in that hole.

Sulph answered 20/1, 2018 at 1:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.