I'm trying to implement an Angular Guard using the Angular Social Login npm package:
@Injectable({
providedIn: 'root',
})
export class LoginGuard implements CanActivate {
constructor(private router: Router, private authService: SocialAuthService) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
console.log('guard');
return this.authService.authState.pipe(
map((socialUser: SocialUser) => {
console.log('map');
return !!socialUser;
}),
catchError((error) => {
console.log(error);
return of(false);
})
);
}
}
I can see guard
being printed to the console. However, I can't see map
printed to the console. Why?
If I do:
@Injectable({
providedIn: 'root',
})
export class LoginGuard implements CanActivate {
constructor(private router: Router, private authService: SocialAuthService) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
console.log('guard');
return new Observable<boolean>((subscriber) => {
console.log('subscriber');
subscriber.next(true);
});
}
}
I can see subscriber
being printed to the console.
What am I doing wrong?
I want to be able to add this Guard to a route. If a user is not logged in, it would be redirected to a login page (I know I'm not yet implementing that logic; I've tried and failed since it seems I'm not getting an Observable with values?). Note that I'm using Google as a provider for this:
@NgModule({
declarations: [
AppComponent,
IndexPageComponent,
SearchPageComponent,
InputKeywordsComponent,
DisplayNewsListComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
HttpClientModule,
SocialLoginModule,
],
providers: [
{
provide: 'SocialAuthServiceConfig',
useValue: {
autoLogin: false,
providers: [
{
id: GoogleLoginProvider.PROVIDER_ID,
provider: new GoogleLoginProvider(
'superVerySecret'
),
},
],
} as SocialAuthServiceConfig,
},
],
bootstrap: [AppComponent],
})
export class AppModule {}
And the routing module:
const routes: Routes = [
{ path: '', component: IndexPageComponent },
{ path: 'search', component: SearchPageComponent, canActivate: [LoginGuard] },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [LoginGuard]
})
export class AppRoutingModule {}
PS1: I can login just fine.
PS2:
Kudos to @msmiechowski for helping me reaching a solution in this GitHub issue.
My solution:
// login.guard.ts
@Injectable({
providedIn: 'root',
})
export class LoginGuard implements CanActivate {
constructor(private router: Router, private loginService: LoginService) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
if (this.loginService.checkAuthState()) {
return of(true);
} else {
this.router.navigateByUrl('/');
return of(false);
}
}
}
// login.service.ts
// ...
checkAuthState(): boolean {
let flag = false;
this.authService.authState.subscribe({
next: (socialUser: SocialUser) => {
if (socialUser) {
flag = true;
}
},
error: (error) => {
console.log(error);
},
complete: () => {
console.log('Complete!');
},
});
return flag;
}
// ...