How can I avoid that my logged-in user goes back to the login url in angular 16?

198 Views Asked by At

I have an angular 16 application and want to avoid that a user that is logged in can return to the login url. It should be possible with an authGuard, but I don't know how I could achieve this. In my app-routing module, I have this:

import { authGuard } from './guards/auth.guard';
import { LoginComponent } from './user/login/login.component';
import { ProfileComponent } from './user/profile/profile.component';
const routes: Routes = [
  { path: '', redirectTo: '/user/profile', pathMatch: 'full' },
  {
    path: 'user',
    children: [
      { path: 'login', component: LoginComponent },
      { path: 'profile', component: ProfileComponent, canActivate: [authGuard] },

      { path: '', redirectTo: 'profile', pathMatch: 'full' },
      { path: '**', redirectTo: 'profile', pathMatch: 'full' },
    ],
  },

  { path: '**', redirectTo: '/user/profile', pathMatch: 'full' }
]
@NgModule({
  imports: [RouterModule.forRoot(routes, { useHash: false })],
  exports: [RouterModule],
})
export class AppRoutingModule {}

and my authGuard looks like this:

import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from '../user/auth.service';
import { inject } from '@angular/core';
import { JwtHelperService } from '@auth0/angular-jwt';

export const authGuard: CanActivateFn = (route, state) => {
  const token = localStorage.getItem('access_token');
  const jwtHelper: JwtHelperService = inject(JwtHelperService);
  const authService = inject(AuthService);
  if (token && !jwtHelper.isTokenExpired(token)) {
    return true;
  } else {
    authService.logout();
    return false;
  }
};

The token authentication works fine, and the user/profile url is properly protected by the authGuard. For user/login however, this does not make sense, since everyone should be able to go to this page.

I tried to put the authGuard at the end of the user path, so it all parent and children paths are guarded, but that causes issues with finding the correct path. I also tried to check in the authGurad if (state.url == '/user/login') {router.navigate(['/user/profile']} but this causes a circular reroute.

1

There are 1 best solutions below

2
Joqsun On

Here is my solution that I came up with a while ago. The paths that should be accessed only after logging in are wrapped in an empty path (notice there is no pathMatch property so it is by default pathMatch: prefix, basically making it act like a wildcard path. This empty path has a canMatch guard which checks whether the user is logged in.

The beauty of this solution is that even if the user enters /user/login in the address bar while logged in, the empty path (and its children) will always be matched so they will not be able to go to the login page.

StackBlitz

{
  path: 'user',
  children: [
    {
      path: '',
      children: [
        { path: 'profile', component: ProfileComponent },
        { path: '**', redirectTo: 'profile' }
      ],
      canMatch: [authGuard]
    },
    { path: 'login', component: LoginComponent },
    { path: '**', redirectTo: 'login' }
  ]
}