In an AngularJS application, users often have different roles (e.g., Admin, User, Guest) that determine which pages they can access. To enforce these permissions, we can use AngularJS routing ($routeProvider
) along with $routeChangeStart
to redirect users based on their roles.
1. Why Implement Role-Based Redirection?
✔ Restrict unauthorized access to certain pages.
✔ Enhance security by preventing direct URL access.
✔ Improve user experience by guiding users to allowed pages.
2. Using $routeProvider
to Define Role-Based Routes
First, define routes in app.config()
and specify role-based access using resolve
.
Example: Configuring Routes for Different Roles
var app = angular.module("myApp", ["ngRoute"]);
app.config(["$routeProvider", function($routeProvider) {
$routeProvider
.when("/", {
templateUrl: "home.html",
controller: "HomeController"
})
.when("/admin", {
templateUrl: "admin.html",
controller: "AdminController",
resolve: {
access: function(AuthService, $q, $location) {
var deferred = $q.defer();
if (AuthService.hasRole("admin")) {
deferred.resolve();
} else {
deferred.reject();
$location.path("/unauthorized");
}
return deferred.promise;
}
}
})
.when("/user", {
templateUrl: "user.html",
controller: "UserController",
resolve: {
access: function(AuthService, $q, $location) {
var deferred = $q.defer();
if (AuthService.hasRole("user")) {
deferred.resolve();
} else {
deferred.reject();
$location.path("/unauthorized");
}
return deferred.promise;
}
}
})
.when("/unauthorized", {
template: "<h2>Access Denied</h2><p>You do not have permission to access this page.</p>"
})
.otherwise({
redirectTo: "/"
});
}]);
How This Works:
- The
resolve
function checks if the user has the required role. - If the user does not have permission, they are redirected to
/unauthorized
.
3. Creating the AuthService for Role-Based Access
Define a simple AuthService
to store and verify user roles.
app.service("AuthService", function() {
var userRole = "guest"; // Default role (can be "admin" or "user")
this.setRole = function(role) {
userRole = role;
};
this.getRole = function() {
return userRole;
};
this.hasRole = function(role) {
return userRole === role;
};
});
How This Works:
setRole(role)
: Sets the user’s role dynamically.getRole()
: Retrieves the current user role.hasRole(role)
: Checks if the user has the required role.
4. Redirect Users Globally with $routeChangeStart
For a centralized way to enforce role-based redirects, listen to route changes in app.run()
.
app.run(["$rootScope", "$location", "AuthService", function($rootScope, $location, AuthService) {
$rootScope.$on("$routeChangeStart", function(event, next) {
if (next.$$route && next.$$route.requiredRole) {
if (!AuthService.hasRole(next.$$route.requiredRole)) {
event.preventDefault(); // Stop navigation
$location.path("/unauthorized"); // Redirect to unauthorized page
}
}
});
}]);
How This Works:
- Before navigating, AngularJS checks if the route has a
requiredRole
. - If the user lacks permission, it prevents navigation and redirects them.
5. Updating Routes to Use requiredRole
Instead of resolve
Now, modify the $routeProvider
routes:
app.config(["$routeProvider", function($routeProvider) {
$routeProvider
.when("/admin", {
templateUrl: "admin.html",
controller: "AdminController",
requiredRole: "admin"
})
.when("/user", {
templateUrl: "user.html",
controller: "UserController",
requiredRole: "user"
})
.when("/unauthorized", {
template: "<h2>Access Denied</h2><p>You do not have permission to access this page.</p>"
})
.otherwise({
redirectTo: "/"
});
}]);
How This Works:
- Instead of using
resolve
, routes now includerequiredRole
. $routeChangeStart
handles redirection globally.
6. Allow Users to Switch Roles Dynamically
In the UI, allow role switching using buttons:
<button ng-click="setRole('admin')">Login as Admin</button>
<button ng-click="setRole('user')">Login as User</button>
<button ng-click="setRole('guest')">Logout</button>
<p>Current Role: {{ currentRole }}</p>
Modify the controller to update roles dynamically:
app.controller("RoleController", ["$scope", "AuthService", function($scope, AuthService) {
$scope.currentRole = AuthService.getRole();
$scope.setRole = function(role) {
AuthService.setRole(role);
$scope.currentRole = role;
};
}]);
Now users can switch roles dynamically!
7. Summary of Role-Based Redirection Approaches
Approach | Pros | Cons |
---|---|---|
resolve in routes | Blocks route before loading | Needs duplication in each route |
$routeChangeStart | Centralized redirection | Requires requiredRole in routes |
Manual role checking in controllers | Full control over logic | More code needed in each page |
Recommended: Use $routeChangeStart
for centralized control.