Access control and permissions in Angular's UI router

I am struggling to figure out how to implement permissions and access control in our Angular app. Currently, our setup looks like this:

app.config(['$stateProvider', function ($stateProvider) {

  $stateProvider

  .state('default', {
    url: '',
    templateUrl: 'pages/home/view/home.html',
    controller: 'HomeCtrl'
  })

  .state('home', {
    url: '/home',
    templateUrl: 'pages/home/view/home.html',
    controller: 'HomeCtrl',

    permissions: {                    // ?
      only: ['Admin','Moderator']
    },

    access: {                         // ?
     roles: ['*']
    },

    resolve: {                        // ?
      authenticate: function($state, $q, $timeout){

      },

    }

  })

}]);

I am unsure of the best approach to take for implementing access control on each page.

Currently, the logged-in user information is stored within an Angular value:

app.value('USER', JSON.parse('{{{user}}}'));

The USER value contains details about the user's roles and permissions.

However, I am unable to inject USER into the app.config() callback as it returns an "unknown provider" error.

How can I enforce access control based on the parameters stored in the USER object?

Answer №1

To effectively implement this, ensure that your access control is added to the event $stateChangeStart.

For instance, if your routing looks like this:

.state('termsofuse', {
    url: "/terms",
    templateUrl: "termOfUse.html",
    resolve: {
        authorizedRoles: function() {
            return [USER_ROLES['su'],
                USER_ROLES['user'],
                USER_ROLES['admin'],
                USER_ROLES['skysu']
            ]
        }
    }
})

You can set up your access control as follows:

.run(function($rootScope, $q, $location, $window, $timeout) {
    $rootScope.$on(
        '$stateChangeStart',
        function(event, next, current) {                      
            var authorizedRoles = next.resolve.authorizedRoles();
        
            // Check if user has necessary roles
            if (!isAuthorized(authorizedRoles)) {
                event.preventDefault();
                $rootScope.$broadcast("AUTH_EVENTS.notAuthenticated");
            } else {
                $rootScope.$broadcast("AUTH_EVENTS.loginSuccess");
            }
        })
});

Then define an event listener to handle the desired behavior (e.g. redirect or display an error message).

Answer №2

Have you considered exploring ngAA? It pairs well with ui-router.

Answer №3

This was the solution I found to make it work. While it may not be perfect, it gets the job done.

It is not possible to inject services or values directly into the app.config(), but you can do so in the resolve.authenticate function.

I opted to follow the resolve.authenticate approach for my implementation.

.state('dashboard', {
    url: '/dashboard',
    templateUrl: 'pages/dashboard/view/dashboard.html',
    controller: 'DashboardCtrl',
    resolve: {
        authenticate: handlePageRequest['dashboard']   // <<<<
    }
})

Additionally, we define a handler as follows:


let handlePageRequest = {

    'default': function ($q, USER, $state, $timeout, AuthService) {
        // This page is always accessible
        return $q.when();
    },

    'dashboard': function ($q, USER, $state, $timeout, AuthService) {

        if (AuthService.isDashboardAccessible(USER)) {
            return $q.when();
        } else {
            $timeout(function () {
                $state.go('unauthorized'); // Preventing access to dashboard page
            }, 100);

            return $q.reject()
        }
    },
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Comparing the syntax of JSON to the switch statement in JavaScript

I recently came across a fascinating post on discussing an innovative approach to utilizing switch statements in JavaScript. Below, I've included a code snippet that demonstrates this alternative method. However, I'm puzzled as to why the alter ...

"Implementing JavaScript Validation for Textboxes: A Step-by-Step Guide

I need some help with restricting the input of a textbox within a gridview to only 'X' or 'O'. I am not very familiar with javascript, so any guidance on how to accomplish this would be greatly appreciated. It's worth noting that t ...

Displaying a loading animation within a specific div element

Is it possible to use jQuery to insert a div into another div? My goal is to replace the contents of one div with a loading div while waiting for an ajax call to return. <div id="content1">foo</div> <div id="content2">bar</div> < ...

Issue with model not displaying after material added in OBLLoader + MTLLoader

After loading a material using MTLLoader and applying it to my model loaded with OBJLoader, the model itself mysteriously disappears. MTLLoader.setPath( 'models/' ); var url = "model.mtl"; MTLLoader.load( url, function( materials ) { materi ...

Tips for identifying the correct selectedIndex with multiple select elements present on one page

How can I maintain the correct selectedIndex of an HTMLSelectElement while having multiple select elements in a loop without any IDs? I am dynamically loading forms on a webpage, each containing a select element with a list of priorities. Each priority is ...

Is it possible that bitwise left shifts in JavaScript ES6 (<<) become cyclical after surpassing a shift of 63?

From my understanding of the << bitwise left operator in JS (ES6), the void to the right is typically filled with zeros. However, through observation in both V8 and JSC, it appears that the set bits suddenly reappear when we shift by 64 or more. (2 ...

Emphasize a thumbnail by decorating it when selected in the gallery display page

I have created a gallery.php file with the following code: <div id="galleryImage"> <ul> <li> <a href= "gallery.php?imgName='artistvan'"> <img src="thumbnail/artistvan.jpg" ti ...

Basic JavaScript Calculator Utilizing JQuery

I have been diligently working on a Javascript Calculator for quite some time now. The CSS and HTML elements seem to be in order. However, the calculator is only functioning properly for sevens and division operations! While the input for other numbers g ...

Encountering a (500 / 503) error on the Heroku application, incorporating Laravel 5.1 and AngularJS, utilizing both GET and POST methods

My goal is to deploy my webapp on Heroku, but I've encountered a problem. Everything was working fine until I started making GET/POST requests, which resulted in a 500 or 503 error. Interestingly, the requests work locally but not on Heroku. [Note: ...

The Authorization Header is added just once during an AJAX CORS request

I am making calls to my RESTful API from JavaScript in a CORS scenario. To send my POST authenticated request, I am utilizing JQuery. Below is an example: function postCall(requestSettings, includeAccessToken) { requestSettings.type = 'POST& ...

What's the best approach: Backbone-Relational discovery or retrieval?

Although the model caching feature in Backbone-Relational is effective, loading a simple model securely requires considerable code. For example: // Attempt to locate a model in the cache this.model = MyModel.find({id:id}); if(this.model){ // Model re ...

Problem with exporting data from the API to a JavaScript file in Excel format

Instead of receiving actual data in the response, I am getting a set of characters. However, everything works fine when I click on Download file in swagger. Can someone help me diagnose the issue? function downloadDocFile(data: Blob, ext = 'xlsx' ...

Change the color when hovering over the select box

Using jQuery, my goal is to change the hover color in a select box from its default blue to red. I understand that the hover color of the select input may vary based on the operating system rather than the browser, but I am making progress towards achievin ...

Creating HTML inputs dynamically using jQuery in an ASP.NET application

I have written this JavaScript code to dynamically generate and add HTML elements within my asp.net webform: var i = 0; function addFields() { i++; var quantity = '<td class="auto-style2"><input type="text" size="3" name= ...

Detecting Unflushed Requests in Jasmine and AngularJS

I'm encountering some issues passing certain tests after implementing $httpBackend.verifyNoOustandingRequest(). Interestingly, excluding this from my afterEach function allows the tests to pass successfully. However, including it causes all tests to ...

Creating a see-through effect in Three.js with React Fiber

I'm currently working with react fiber and struggling to make the background of my child scene transparent. Below is my root component containing the main Canvas element: export const Splash = () => { const { intensity, distance, colo ...

Font Family Not Recognized in React Native

Encountering an unusual issue while working with React Native. In my button.js file, I have the following code: import Icon from "react-native-vector-icons/MaterialIcons"; const icon = (Icon name="menu size={20} color="green"/>); render() return( ...

Ways to avoid overflow of dynamically added div element?

Currently, I am facing an issue while dynamically appending div elements with the .magnet class to my page. These elements end up overflowing the container boundaries and I am struggling to find a solution for this problem. If anyone could check out my j ...

Click on the navigation bar buttons to toggle between different divs and display multiple information boxes simultaneously

Here is the current code snippet... $("#contact").click(function() { if ( $( "#contact_div" ).length ) { $("#contact_div").remove(); } else { var html='<div id="contact_div" class="contact-info"><p>Contact info</p&g ...

Ensuring the accuracy of dynamic form data in Angular before submission

When I dynamically create forms using ng-repeat, they include validation attributes as shown below: <div class="row" ng-repeat="defect in model.defects"> <form name="form_{{defect.id}}" novalidate> <input ng-model="defect.name" re ...