I have an authentication service which is used in both the admin and user portions of my site, but connects to different endpoints on the backend API. I am using Factories to provide the different services based on which module is loaded (admin vs user).
However, when I attempt to create an AuthGuard service and inject my AuthService, it always generates a separate instance of the AuthService when the router calls CanActivate. Is the router somehow working outside the scope of the lazy-loaded module and that is why it's generating a new instance?
auth.provider.ts
let AuthFactory = (
http: Http,
router: Router,
storageService: StorageService,
modalService: NgbModal,
isAdmin: boolean
) => {
return new AuthService(http, router, storageService, modalService, isAdmin);
};
export let AuthProvider = {
provide: AuthService,
useFactory: AuthFactory,
deps: [ Http, Router, StorageService, NgbModal, IS_ADMIN ]
};
app.routing.ts
const appRoutes: Routes = [
{
path: 'mgmt',
loadChildren: 'app/admin/admin.module'
},
{ path: '',
loadChildren: 'app/users/users.module'
},
{ path: '**',
redirectTo: ''
}
];
@NgModule({
imports: [ RouterModule.forRoot(appRoutes)],
exports: [ RouterModule ]
})
export class AppRoutingModule {}
admin.routing.ts
RouterModule.forRoot(appRoutes);
const routes: Routes = [
{ path: '',
component: AdminComponent,
children: [
{
path: '',
component: DashboardComponent,
canActivate: [AuthGuard],
{
path: '**',
redirectTo: ''
}
]
}
];
@NgModule({
imports: [ RouterModule.forChild(routes)],
exports: [ RouterModule ]
})
export class AdminRoutingModule {}
auth-guard.service.ts
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService,
private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.authService.authenticated()
.map(authenticated => {
if (authenticated) {
return true;
} else {
// do some other things
return false;
}
})
.take(1);
}
}
You are constructing a new AuthProvider each time because of a new use of AuthFactory. You should move to a "singleton" design pattern, where the factory provides the constructor and then a getter method returns either the existing AuthProvider or a new one, if it does not already exist. That way you're always referencing a single instance of the object.
Check out plenty of resources on implementing singletons in javascript.