46

EDIT : Obviously this is outdated, now you provide your guard at the providers array in an NgModule. Watch other answers or official documentation for more information.

  • bootstrapping on a component is outdated
  • provideRouter() is outdated as well


I'm trying to setup Authentication in my project, using a login and AuthGuard from the Angular2 guide : https://angular.io/docs/ts/latest/guide/router.html

I'm using the release : "@angular/router": "3.0.0-beta.1".

I'll try to explain as much as possible, feel free to tell me if you need more details.


I have my main.ts file which boostraps the app with the following code :

bootstrap(MasterComponent, [
    APP_ROUTER_PROVIDERS,
    MenuService
])
.catch(err => console.error(err));

I load the MasterComponent, which loads a Header containing buttons that allow me to navigate through my app and it also contains my main for now.

I'm following the guide to make my app work the same way, with the following app.routes.ts :

export const routes: RouterConfig = [
    ...LoginRoutes,
    ...MasterRoutes
];

export const APP_ROUTER_PROVIDERS = [
    provideRouter(routes),
    AUTH_PROVIDERS
];

And the login.routes.ts from the guide, which defines my AuthGuard :

export const LoginRoutes = [
    { path: 'login', component: LoginComponent }
];

export const AUTH_PROVIDERS = [AuthGuard, AuthService];

my Master component has its own route definition, which also contains the guard I'm trying to setup. master.routes.ts :

export const MasterRoutes : RouterConfig = [
    { path: '', redirectTo: '/accueil', pathMatch: 'full' },

    {
        path: 'accueil',
        component: AccueilComponent
    },

    { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },
];

And I'm using the same files as the guide, which are auth.guard.ts, auth.service.ts, login.component.ts and login.routes.ts.


In my header.component.ts file, when I try to access any routes, it's working just fine, but when I try to access the guarded path (/dashboard), I get the No provider for AuthGuard! error.

I saw the recent post with the same issue as mine (NoProviderError using CanActivate in Angular 2), but to me the guard is bootstraped correctly up to the main.ts file, so my router should know which routes should be provided with the AuthGuard right ?

Any help or advice would be greatly appreciated. Thanks !

17
  • Did you import AuthGuard into master.routes.ts and login.routes.ts? Commented Jul 5, 2016 at 12:40
  • Yes, I did import them correctly. I did not mention it, but I manually navigate to the route because I wanted to link on a <button> using this.router.navigate(['/dashboard']); Commented Jul 5, 2016 at 12:42
  • 1
    See stackoverflow.com/questions/38144547/… Commented Jul 5, 2016 at 12:51
  • 1
    Weird thing is that my company's firewall is actually blocking the plunkr links, so I may need a bit of time... I'll edit this comment with a working plunkr hopefully Commented Jul 5, 2016 at 13:13
  • 1
    You're welcome. Glad to hear you figured it out. Commented Jul 5, 2016 at 14:14

12 Answers 12

86

I had this same issue after going through the Route Guards section of Routing and Authorization tutorial on the Angular website https://angular.io/docs/ts/latest/guide/router.html, it is section 5.

I am adding AuthGuard to one of my main routes and not to child routes like the tutorial shows.

I fixed it by added AuthGuard to my list of providers in my app.module.ts file, so that file now looks like this:

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { AuthGuard } from './auth-gaurd.service';

import { AnotherPageComponent } from './another-page/another-page.component';
import { LoginPageComponent } from './login-page/login-page.component';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    JsonpModule,
    AppRoutingModule,
    HttpModule
  ],
  declarations: [
    AppComponent,
    LoginPageComponent,
    AnotherPageComponent
  ],
  providers: [AuthGuard],
  bootstrap: [AppComponent]
})

export class AppModule { }

I have gone back through the tutorial and in their app.module.ts file, they do not add AuthGuard to the providers, not sure why.

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

1 Comment

it is kind of interesting that I did not need to add guards to providers, and the books I am reading asks to, I have no idea why my app is working without it! that is why I have found this question, my app works, and I have not add to the providers, I am using lazy load.
33

Try to add

@Injectable({ providedIn: 'root' }) no need to add to module provider.

Comments

18

Also, don't fall into the trap of using a literal for the guard class inside your routing configuration, just because some blog articles do:

{ path: 'whatever', component: WhatEverComponent, canActivate: ['WhatEverGuard'] }

is not going to work (No provider for...), instead, use the class directly:

{ path: 'whatever', component: WhatEverComponent, canActivate: [WhatEverGuard] }

Another hint, when lazy loading components, the guard is applied in the routing configuration of the parent component, not in the routing configuration of the lazy loaded component.

3 Comments

I put WhatEverGuard into single quotes, and it showed me No provider .. that was so annoying
Me too. I had: canActivate: [ 'AuthGuard', AuthGuard ] As soon as I removed the literal it worked.
oh my God, you genius! thank you for this answer, the stupid tutorial I was following has used single quotes exactly like you describe!
12

For those who still have this error - don't forget to include your AuthGuard service or class to main bootstrap function. And don't forget to import this service before bootstrap runs.

import { bootstrap } from '@angular/platform-browser-dynamic';

import { AppComponent } from './app.component';
import { AuthGuard } from './shared/auth.service';

bootstrap(AppComponent, [
  appRouterProviders,
  AuthGuard
]);

Angular 2 team did not mention this in main router docs, and it took couple of hours for me to figure it out.

Comments

7

The answer is further down in the tutorial. See the file listings in the "Add the LoginComponent" topic under the "Component-less route:..." section in "Milestone 5: Route Guards". It shows AuthGuard and AuthService being imported and added to the providers array in login-routing.module.ts, and then that module being imported into app.module.ts.

login-routing.module.ts

  ...
    import { AuthGuard }            from './auth-guard.service';
    import { AuthService }          from './auth.service';
    ...
    @NgModule({
    ...
      providers: [
        AuthGuard,
        AuthService
      ]
    })
    export class LoginRoutingModule {}

app.module.ts

import { LoginRoutingModule }      from './login-routing.module';

@NgModule({
  imports: [
    ...
    LoginRoutingModule,
    ...    
  ],
  ...
  providers: [
    DialogService
  ],
  ...

1 Comment

Thanks for this, I was stuck on the tutorial and this helped a lot. I thought that they should be in the appModule, but they aren't in the final version of the code and I couldn't figure out how it worked without them.
6

I encountered this issue when I was following a tutorial. I tried most of the answer here but not getting any success. Then I tried the silly way like putting the AuthGuard before the other services in the provider and it works.

// app.module.ts

 .. 
 providers: [
   AuthGuard,
   UserService,
   ProjectService
  ]

Comments

5

Actually, it was only a typo in an import...

I was typing

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

instead of

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

making it not working but at the same time not displaying me any error...

(sadface)

3 Comments

Thats why it is recommended to use typescript aware editor like Visual studio code ( its the best ).
Yes, I've been using VS 2015 but clearly, it's not as good as Visual Code.
I faced same kind of issue, finally found the issue is the import path is case sensitive
2

Since you got the solution as it was due to syntax issue. I just wanted to share this info.

we need to provide the AuthGaudSerivce as provider in only that module that correspond to respective route. No need to provide in main module or root module as main module will automatically load all the given sub module.This helps in keeping the code modular and encapsulated.

for example, suppose we have below scenario

1. we have module m1
2. we have route m1r in module m1
3. route m1r has 2 route r1 and r2
4. we want to protect r1 using authGaurd
5. finally we have main module that is dependent on sub module m1 

Below is just prototype, not the actual code for understanding purpose

//m1.ts    
import {AuthGaurd} from './auth.gaurd.service'
import {m1r} from './m1r'
    @NgModule(
     imports: [m1r],
     providers: [AuthGaurd]
    )
    export class m1{
    }

//m1r.ts
import {AuthGaurd} from './auth.gaurd.service'
const authRoute = [
 {path: '/r1', component: 'authComponent', canActivate: [AuthGaurd]},
 {path: '/r2', component: 'other'}
]
export authRoute

//main.module.ts
import {m1} from ''
import {mainComponent} from ''
@NgModule({
  imports: [m1],
  bootstrap: [mainComponent]
  })
export class MainModule{}    

1 Comment

You missed AuthGuard
1
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

@Injectable()
export class AuthGuard implements CanActivate {

    constructor(private router: Router) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        if (localStorage.getItem('currentUser')) {
            // logged in so return true
            return true;
        }

        // not logged in so redirect to login page with the return url
        this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});
        return false;
    }
}

1 Comment

Please explain your solution, and how fixes the problem
1

Importing both HttpModule and HttpClientModule helped me.

import { HttpClientModule } from '@angular/common/http'; 
import { HttpModule } from '@angular/http';

Comments

0

you can try import AuthGuard in provider of that module and then import it in the routing component-routing.module.ts file also

@NgModule({
providers: [
    AuthGuard
  ],})

Comments

0

This happened to me when I had setup my Routes incorrectly:

WRONG

const routes: Routes = 
[
  { 
    path: 'my-path', 
    component: MyComponent, 
    resolve: { myList: MyListResolver, canActivate: [ AuthenticationGuard ] } 
  },
];

Note that in this case canActivate was accidentally made a part of the resolve object.

CORRECT

const routes: Routes = 
[
  { 
     path: 'my-path', 
     component: MyComponent, 
     resolve: { myList: MyListResolver }, 
     canActivate: [ AuthenticationGuard ] 
  },
];

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.