AngularFireAuthGuard redirectUrl after login

1k views Asked by At

I use firebase and AngularFireAuthGuard to protect specific routes, so that only authenticated users are allowed to access them. In particular, my MainComponent and MgmtComponent should only be accessible to AUTHENTICATED users.

const redirectUnauthorizedToLogin = () => redirectUnauthorizedTo(['/login']);

const routes: Routes = [
  { path: 'teams/:teamId/sessions/:sessionId',
    component: MainComponent,
    canActivate: [AngularFireAuthGuard], data: { authGuardPipe: redirectUnauthorizedToLogin }
  },
  { path: 'mgmt',
    component: MgmtComponent,
    canActivate: [AngularFireAuthGuard], data: { authGuardPipe: redirectUnauthorizedToLogin }
  },
  {
    path: 'login',
    component: LoginComponent
  }
];

My Problem is, that the user is not redirected back to the originally requested URL, after a successful login. So what I want/expect is:

  1. user goes to /mgmt
  2. as the user is not authenticated he is automatically redirected to /login
  3. user authenticates (e.g. via google or Facebook OAuth)
  4. user is automatically redirected back to the originally requested page (/mgmt)

Steps 1-3 work fine, but step 4 is missing.

2

There are 2 answers

0
Herbi On

This is an open feature request, the angularfire team is working on it: https://github.com/angular/angularfire/pull/2448

Meanwhile I found this workaround: In the app-routing-module.ts instead of

const redirectUnauthorizedToLogin = () => redirectUnauthorizedTo(['/login']);

I use following to store the url in the sessionStorage:

const redirectUnauthorizedToLogin = (route: ActivatedRouteSnapshot) => {
  const path = route.pathFromRoot.map(v => v.url.map(segment => segment.toString()).join('/')).join('/');

  return pipe(
    loggedIn,
    tap((isLoggedIn) => {
      if (!isLoggedIn) {
        console.log('Saving afterLogin path', path);
        sessionStorage.setItem('afterLogin', path);
      }
    }),
    map(loggedIn => loggedIn || ['/login'])
  );
};

In the LoginComponent I read the value from the session storage to redirect:

sessionStorage.getItem('afterLogin');
this.router.navigateByUrl(redirectUrl);
1
waternova On

Now that the feature request is in, you can do this using the auth guard. However, the docs are unclear, so here is how I did it.

/** add redirect URL to login */
const redirectUnauthorizedToLogin = (next: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
  return redirectUnauthorizedTo(`/login?redirectTo=${state.url}`);
};

/** Uses the redirectTo query parameter if available to redirect logged in users, or defaults to '/' */
const redirectLoggedInToPreviousPage = (next: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
  let redirectUrl = '/';
  try {
    const redirectToUrl = new URL(state.url, location.origin);
    const params = new URLSearchParams(redirectToUrl.search);
    redirectUrl = params.get('redirectTo') || '/';
  } catch (err) {
    // invalid URL
  }
  return redirectLoggedInTo(redirectUrl);
};