Search code examples
angularfirebase-authenticationangularfire2

How to make an AngularFire route guard that redirects unauthorized users back to landing page?


This route guard blocks unauthorized access to my-project.com/home but it redirects users to a blank page, not to my landing page.

app-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthPipe, AuthGuard, AuthGuardModule, AuthPipeGenerator, canActivate, hasCustomClaim, idTokenResult, isNotAnonymous, loggedIn, redirectLoggedInTo, redirectUnauthorizedTo, customClaims, emailVerified, } from '@angular/fire/auth-guard';

// components
import { LandingComponent } from './landing/landing.component';
import { HomeComponent } from './home/home.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';

const routes: Routes = [
  { path: 'landing', component: LandingComponent },
  { path: 'default', component: LandingComponent },
  { path: 'home', component: HomeComponent, canActivate: [AuthGuard], data: { authGuardPipe: redirectUnauthorizedTo(['landing']) }}, // route guard is here
  { path: '', component: LandingComponent },
  { path: '**', component: PageNotFoundComponent },
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes),
    provideAuth(() => getAuth()),
    AuthGuardModule,
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

This route didn't compile:

{ path: 'home', component: HomeComponent, canActivate(() => redirectUnauthorizedTo(['/landing'])) },

That threw this error message:

TS2349: This expression is not callable.
Type '{ path: string; component: typeof HomeComponent; canActivate(): any; }' has no call signatures.

I tried AuthPipe and AuthPipeGenerator instead of authGuardPipe (which isn't a method of '@angular/fire/auth-guard').

I imported Auth and Auth-Guard into app.module.ts but that didn't help.

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { provideAuth, getAuth, } from '@angular/fire/auth';
import { AuthGuardModule } from '@angular/fire/auth-guard';

@NgModule({
  imports: [
    AppRoutingModule,
    provideAuth(() => getAuth()),
    AuthGuardModule, 

Solution

  • I figured it out. I was missing

    const redirectUnauthorizedToLanding = () => redirectUnauthorizedTo(['landing']);
    

    Now my code works.

    import { NgModule } from '@angular/core';
    import { RouterModule, Routes } from '@angular/router';
    import { AuthGuard, redirectUnauthorizedTo } from '@angular/fire/auth-guard';
    
    // components
    import { LandingComponent } from './landing/landing.component';
    import { HomeComponent } from './home/home.component';
    import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
    
    const redirectUnauthorizedToLanding = () => redirectUnauthorizedTo(['landing']); // this was missing
    
    const routes: Routes = [
      { path: 'landing', component: LandingComponent },
      { path: 'default', component: LandingComponent },
      { path: 'home', component: HomeComponent, canActivate: [AuthGuard], data: { authGuardPipe: redirectUnauthorizedToLanding }},
      { path: '', component: LandingComponent },
      { path: '**', component: PageNotFoundComponent },
    ];
    
    @NgModule({
      imports: [
        RouterModule.forRoot(routes),
      ],
      exports: [RouterModule]
    })
    export class AppRoutingModule { }
    

    No need to import '@angular/fire/auth' into app-routing.module.ts.

    No need to import '@angular/fire/auth-guard' into app.module.ts.