> For the complete documentation index, see [llms.txt](https://codedthemes.gitbook.io/berry-angular/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://codedthemes.gitbook.io/berry-angular/how-to/role-base-authentication.md).

# Role Base Authentication

1. The main routing file defines route paths and lazy-loaded modules for various components based on the user's role.

{% code title="src/app-routing.module.ts" %}

```typescript
`
// angular imports
import { Routes } from '@angular/router';

// project import
import { AdminComponent } from './theme/layout/admin/admin.component';
import { GuestComponent } from './theme/layout/guest/guest.component';
import { authGuardChild } from './theme/shared/_helpers/auth.guard';
import { Role } from './theme/shared/_helpers/role';

const routes: Routes = [
 .....
{
    path: '',
    component: AdminComponent,
    canActivateChild: [AuthGuardChild],
    children: [
      {
        path: '',
        loadComponent: () => import('./demo/dashboard/default/default.component').then((c) => c.DefaultComponent),
        data: { roles: [Role.Admin, Role.User] }
      },
      {
        path: 'default',
        loadComponent: () => import('./demo/dashboard/default/default.component').then((c) => c.DefaultComponent),
        data: { roles: [Role.Admin, Role.User] }
      },
      {
        path: 'analytics',
        loadComponent: () => import('./demo/dashboard/analytics/analytics.component').then((c) => c.AnalyticsComponent),
        data: { roles: [Role.Admin] }
      },
      ....
    ]
    ....
}
 
```

{% endcode %}

2. **Child Routing Module:** Defines the child routes and applies role-based access.

{% code title="src/app/demo/admin-panel/online-courses/online-courses-routing.ts" %}

```typescript
// angular imports
import { Routes } from '@angular/router';

// project import
import { APP_TITLE } from 'src/app/app-config';

export const OnlineCoursesRoutes: Routes = [
  {
    path: '',
    children: [
      {
        path: 'dashboard',
        loadComponent: () => import('./online-dashboard/online-dashboard.component').then((c) => c.OnlineDashboardComponent),
        data: { roles: [Role.Admin] },
        title: `Online Courses | ${APP_TITLE}`
      },
      {
        path: 'teacher',
        loadChildren: () => import('./teacher/teacher-routing').then((m) => m.TeacherRoutes),
        data: { roles: [Role.Admin, Role.User] },
        title: `Teacher | ${APP_TITLE}`
      },
      .....
      {
        path: 'setting',
        loadChildren: () => import('./setting/setting-routing').then((m) => m.SettingRoutes),
        data: { roles: [Role.Admin, Role.User] },
        title: `Setting | ${APP_TITLE}`
      }
    ]
  }
];
```

{% endcode %}

3. Role Management

{% code title="src/app/theme/shared/\_helpers/role.ts" %}

```typescript
export enum Role {
  User = 'User',
  Admin = 'Admin'
}
```

{% endcode %}

4. **Authentication Guard**: This `AuthGuardChild` ensures that users can only access authorised routes.

{% code title="src/app/theme/shared/\_helpers/auth.guard.ts" %}

```typescript
import { inject } from '@angular/core';
import { Router, ActivatedRouteSnapshot, RouterStateSnapshot, CanActivateChildFn } from '@angular/router';
import { Observable, of, map, catchError } from 'rxjs';

import { AuthenticationService } from '../service/authentication.service';
import { User } from './user';

import { AuthenticationService } from '../service/authentication.service';
import { User } from './user';

function checkAuthorization(route: ActivatedRouteSnapshot, state: RouterStateSnapshot, currentUser: User, router: Router): boolean {
  const { roles } = route.data;
  if (roles && !roles.includes(currentUser.user.role)) {
    router.navigate(['/unauthorized']);
    return false;
  }
  return true;
}

export const authGuardChild: CanActivateChildFn = (
  route: ActivatedRouteSnapshot,
  state: RouterStateSnapshot
): boolean | Observable<boolean> => {
  const router = inject(Router);
  const authenticationService = inject(AuthenticationService);

  const currentUser = authenticationService.currentUserValue;
  const hasToken = !!authenticationService.getToken();

  // If we have a token but no user data, fetch it first
  if (hasToken && !currentUser && !authenticationService.isLoading) {
    return authenticationService.fetchCurrentUser().pipe(
      map((user) => {
        authenticationService.isLogin = true;
        return checkAuthorization(route, state, user, router);
      }),
      catchError(() => {
        router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
        return of(false);
      })
    );
  }

  // If user data is currently loading, wait for it to complete
  if (authenticationService.isLoading) {
    return new Observable<boolean>((observer) => {
      let attempts = 0;
      const maxAttempts = 50; // 5 seconds max (50 * 100ms)

      const checkInterval = setInterval(() => {
        attempts++;
        if (!authenticationService.isLoading || attempts >= maxAttempts) {
          clearInterval(checkInterval);
          const user = authenticationService.currentUserValue;
          if (user && authenticationService.isLoggedIn()) {
            observer.next(checkAuthorization(route, state, user, router));
          } else {
            router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
            observer.next(false);
          }
          observer.complete();
        }
      }, 100);
    });
  }

  // If we have user data, check authorization
  if (currentUser && authenticationService.isLoggedIn()) {
    return checkAuthorization(route, state, currentUser, router);
  }

  // User not logged in, redirect to login page
  router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
  return false;
};


```

{% endcode %}
