Full Angular RBAC + Permission System (ULTIMATE)

Full Angular RBAC + Permission System (ULTIMATE)

You will get:

  • ✅ Backend-driven Roles + Permissions
  • ✅ Angular stores user access
  • ✅ Dynamic menus (Task C)
  • ✅ Route guard (Task D)
  • ✅ API protection (Task E)
  • ✅ Admin can assign permissions (concept)
  • ✅ Supports Permission Groups, Feature Flags, Multi-role users
  • ✅ Clean enterprise architecture

🧠 Enterprise Concept (Real World)

After login, backend returns:


{
  "userId": 101,
  "name": "Sai",
  "roles": ["Admin"],
  "permissions": [
    "DASHBOARD_VIEW",
    "USERS_VIEW",
    "USERS_CREATE",
    "REPORTS_VIEW",
    "SETTINGS_VIEW"
  ]
}

Angular uses this for:

  • Menu show/hide
  • Route guard
  • API guard
  • UI button enable/disable

1️⃣ Auth State Model (Enterprise)


// auth-state.model.ts
import { Permission, Role } from './permission.model';

export interface AuthUser {
  userId: number;
  name: string;
  roles: Role[];
  permissions: Permission[];
}

2️⃣ AuthStore Service (Central State)

BEST enterprise pattern using BehaviorSubject.


// auth-store.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { AuthUser } from './auth-state.model';

@Injectable({ providedIn: 'root' })
export class AuthStoreService {

  private userSubject = new BehaviorSubject(null);

  user$ = this.userSubject.asObservable();

  setUser(user: AuthUser) {
    this.userSubject.next(user);
  }

  getUser(): AuthUser | null {
    return this.userSubject.value;
  }

  clearUser() {
    this.userSubject.next(null);
  }
}

3️⃣ Update PermissionService to use AuthStore


// permission.service.ts
import { Injectable } from '@angular/core';
import { AuthStoreService } from './auth-store.service';
import { Permission, Role } from './permission.model';

@Injectable({ providedIn: 'root' })
export class PermissionService {

  constructor(private authStore: AuthStoreService) {}

  private get roles(): Role[] {
    return this.authStore.getUser()?.roles ?? [];
  }

  private get permissions(): Permission[] {
    return this.authStore.getUser()?.permissions ?? [];
  }

  hasPermission(permission: Permission): boolean {
    return this.permissions.includes(permission);
  }

  hasAnyPermission(permissions: Permission[]): boolean {
    return permissions.some(p => this.hasPermission(p));
  }

  isInRole(role: Role): boolean {
    return this.roles.includes(role);
  }
}

4️⃣ Login Flow: Store User + Tokens


// auth.service.ts (login part)
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, tap } from 'rxjs';
import { TokenService } from './token.service';
import { AuthStoreService } from './auth-store.service';
import { AuthUser } from './auth-state.model';

export interface LoginResponse {
  accessToken: string;
  refreshToken: string;
  user: AuthUser;
}

@Injectable({ providedIn: 'root' })
export class AuthService {

  private baseUrl = 'https://localhost:5001/api/auth';

  constructor(
    private http: HttpClient,
    private tokenService: TokenService,
    private authStore: AuthStoreService
  ) {}

  login(email: string, password: string): Observable {
    return this.http.post(`${this.baseUrl}/login`, { email, password }).pipe(
      tap(res => {
        this.tokenService.setTokens(res.accessToken, res.refreshToken);
        this.authStore.setUser(res.user);
      })
    );
  }

  logout() {
    this.tokenService.clearTokens();
    this.authStore.clearUser();
    window.location.href = "/login";
  }
}

5️⃣ Persist User on Refresh (IMPORTANT)

Store user in localStorage to survive browser refresh:


// auth-store.service.ts (upgrade)
private userKey = "auth_user";

setUser(user: AuthUser) {
  localStorage.setItem(this.userKey, JSON.stringify(user));
  this.userSubject.next(user);
}

loadUserFromStorage() {
  const data = localStorage.getItem(this.userKey);
  if (data) {
    this.userSubject.next(JSON.parse(data));
  }
}

clearUser() {
  localStorage.removeItem(this.userKey);
  this.userSubject.next(null);
}

6️⃣ Call loadUserFromStorage() in App Startup


// app.component.ts
import { Component } from '@angular/core';
import { AuthStoreService } from './core/auth/auth-store.service';

@Component({
  selector: 'app-root',
  template: ``
})
export class AppComponent {
  constructor(private authStore: AuthStoreService) {
    this.authStore.loadUserFromStorage();
  }
}

7️⃣ RBAC: Button Level Permissions

Example: Hide "Create User" button if no permission.


// users.component.html

8️⃣ Ultimate: Feature Module Protection


// users-routing.module.ts
const routes: Routes = [
  {
    path: '',
    canActivate: [PermissionGuard],
    data: { permissions: ['USERS_VIEW'] },
    component: UsersListComponent
  },
  {
    path: 'create',
    canActivate: [PermissionGuard],
    data: { permissions: ['USERS_CREATE'] },
    component: UsersCreateComponent
  }
];

9️⃣ Ultimate: Backend Driven Menu (REAL Enterprise)

Instead of hardcoding menu config, backend returns:


[
  {
    "label": "Dashboard",
    "route": "/dashboard",
    "icon": "dashboard",
    "permissions": ["DASHBOARD_VIEW"]
  }
]

Angular filters and shows menu items dynamically.

🔟 Backend Database Design (Interview Gold)

Tables:

  • ✅ Users
  • ✅ Roles
  • ✅ Permissions
  • ✅ UserRoles
  • ✅ RolePermissions
  • ✅ RefreshTokens

🔥 11️⃣ Permission Groups (MEGA Enterprise)

Instead of 100 permissions, group them:

  • USERS: VIEW, CREATE, UPDATE, DELETE
  • REPORTS: VIEW, EXPORT
  • SETTINGS: VIEW, UPDATE

🔥 12️⃣ Full Enterprise Flow Summary

  • Login: Get tokens + roles + permissions, save to storage, load on refresh
  • UI: Menu filtered, buttons hidden, routes blocked, APIs protected
  • Token expiry: Refresh token interceptor retries automatically

⭐ Interview One-Liner (SUPER STRONG)

I implemented a complete RBAC system in Angular where permissions from backend control UI menus, route access, button visibility, and API calls using directives, guards, interceptors, and centralized auth store.

Comments

Popular posts from this blog

Debouncing & Throttling in RxJS: Optimizing API Calls and User Interactions

Promises in Angular

Comprehensive Guide to C# and .NET Core OOP Concepts and Language Features