AngularJS - ensure that only authenticated users are allowed to access specific routes

Within my application, I have an authService that manages the isAuthenticated flag when a user is logged in. Each time there is a route change, a listener is triggered by the $routeChangeStart event to verify if the user is authenticated using authService.isAuthenticated(). If not, the user should be redirected to the login route.

The issue arises when a user performs a page refresh and all the settings from authService are cleared, leading them back to the login screen despite having a valid session on the server. This behavior is not desired.

My goal is to delay the route change until I can determine if the user is authenticated - either through immediate verification with authService, or by retrieving the information from the server if it's not available in authService (e.g. after a refresh). The authService includes a function for this:

// returns promise
currentUser: function() {
    if (authService.isAuthenticated()) {
        return $q.when(authService.loggedUser);
    }
    return $http.get('/session').then(function(response) {
        authService.loggedUser = response.user;
        return $q.when(authService.loggedUser);
    });
}

I intend to utilize this function within the event listener:

$rootScope.$on("$routeChangeStart", function (event, next, current) {
    if(isRouteRestricted(next)) {
        authService.currentUser().then(null, function() {
            $location.path('/login');
        });
    }
});

However, the implementation does not behave as expected. The target route is still briefly visible before the redirection occurs. I suspect this is related to the asynchronous nature of promises, but how can I prevent this "blink" effect?

Answer №1

In the main controller, I would implement something similar to this approach, where the initial controller called upon page refresh is considered the top level controller (please excuse any errors in the javascript code, as my expertise lies more in coffeescript):

var authenticationRequired = function (event, next, current) {
    if(isRouteRestricted(next)) {
        authService.currentUser().then(null, function() {
            $location.path('/login');
        });
    }
}

authenticationRequired(null, getUpdatedDetails).then(function () {
    // All of your important controller logic can be executed here, possibly within a separate function
});

$rootScope.$on("$routeChangeStart", authenticationRequired);

By setting up this structure, it ensures that the controller code will not run until the authentication checks have successfully completed.

Answer №2

Here are steps to prevent a user from accessing routes:

Firstly, define your routes and include a property like 'access' : allowAnonymous : true or false

// in app.js
var myApp = angular.module('myApp',['ngResource', 'ngCookies', 'ngRoute']);       
myApp.config(function ($httpProvider, $routeProvider) {
   window.routes = {
        '/Login':
           { templateUrl: '/Account/Login',
             controller: 'AccountController',
             access : {allowAnonymous : true}
           },
        '/MembersPage':
           { templateUrl: '/Home/SomePage,
             controller: SomePageController',
             access: {allowAnonymous:false}
           }
         };

        for (var path in window.routes) {
           $routeProvider.when(path, window.routes[path]);
    }
    $routeProvider.otherwise({ redirectTo: '/Login' });
});   

Secondly, identify an authenticated user:

To achieve this, create a 'UserService' in AngularJS that stores the current user's name and authentication status.

// in UserService.js
myApp.factory('userService', function () {
var user = {
    isLogged: false,
    username: '',       
};

var reset = function() {
    user.isLogged = false;
    user.username = '';
};

return {
    user: user,
    reset : reset
  };
});

Lastly, capture route change events and handle them accordingly:

Implement functionality to check if a user is authenticated when navigating routes using methods like '$routeChangeStart' and '$locationChangeStart'. If the user is not logged in and tries to access a restricted route, display an error message and redirect them to the login page.

// in RootController.js
myApp.controller('RootController',
function ($scope, $route, $routeParams, $location, $rootScope, authenticationService,   
userService, toaster) {
 $scope.user = userService.user;
 $scope.$on('$routeChangeStart', function (e, next, current) {               
     if (next.access != undefined && !next.access.allowAnonymous && !$scope.user.isLogged) {
                $location.path("/Login");                   
            }
        });

        $scope.logout = function () {
            authenticationService.logout()
                .success(function (response) {
                    userService.reset();                       
                    toaster.pop("info", 'You are logged out.', '');
                });
        };

 $rootScope.$on("$locationChangeStart", function (event, next, current) {
  for (var i in window.routes) {
    if (next.indexOf(i) != -1) {
     if (!window.routes[i].access.allowAnonymous && !userService.user.isLogged) {
          toaster.pop("error", 'You are not logged in!', '');
             $location.path("/Login");                                                 
                    }
                }
            }
        });
    });

For more information, visit

Hope this guide helps!

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

When setting an empty URL with Fabricjs' setBackgroundImage function, a null reference error occurs in the _setWidthHeight

Recently, I stumbled upon an article detailing a method to clear the background of a fabric canvas... canvas.setBackgroundImage('', canvas.renderAll.bind(canvas)); In the development of my online design tool which utilizes Fabricjs 1.4.4, I have ...

Utilizing the W3Schools CodeColor library across various elements

Looking to provide code examples using a JS code highlighter with an ID? Check out this URL for a demonstration: https://www.w3schools.com/howto/tryit.asp?filename=tryhow_syntax_highlight Want to use this for multiple examples but finding that the ID only ...

Assign a value to a text input using React

Whenever the closeEmail function is triggered or called, I need to set the email.emailAddress as the value of the textfield. I'm fairly new to React, what is the syntax or method to achieve this? Any suggestions? #code snippet <div style={{ disp ...

The straightforward onclick action only functioned once

Looking for assistance: Can someone explain why this code snippet isn't functioning properly? It seems that the increment is only happening once. var player = document.getElementById("player"); var button = document.getElementById("button"); functio ...

Having difficulty constructing the tree hierarchy in a React project

Trying to implement a tree view in React but struggling with constructing the hierarchical view of information. Reference: https://www.w3schools.com/howto/howto_js_treeview.asp Example on CodeSandbox: https://codesandbox.io/s/unruffled-babbage-9knrz?file ...

Leveraging client API callback variables within a Node.js backend system

If I send a request on the client side using the code snippet below public/foo.js function bar() { fetch('https://api.github.com/') .then(response => response.json()) .then(data => { console.log(data) }) .catch( ...

How to open a hyperlink in a separate background tab with JavaScript or jQuery

I am in need of a feature that automatically opens all links on a website in a new background tab when a user clicks on them. Despite searching extensively, I have not found a solution that works across all browsers. To implement this, I have referred to t ...

Error: The function `map` cannot be applied to `cardsData`

I'm encountering an issue where I need to store user queries in cardsData and then map through the data within cardsData. However, when I run the code on my terminal, it throws an error. As a beginner, I've researched various forums that mention ...

Is it possible to establish role-based access permissions once logged in using Angular 6?

Upon logging in, the system should verify the admin type and redirect them to a specific component. For example, an HOD should access the admi dashboard, CICT should access admin2 dashboard, etc. Below is my mongoose schema: const mongoose = require(&apo ...

Encountering a Node V18 Peer Dependency Conflict错

Can someone please help me understand what's causing this error? Every time I try to install a dependency, this keeps popping up. I'm completely lost and unsure of what's happening. npm ERR! 1 more (the root project) npm ERR! peer ...

Testing Redirects with Protractor and Jasmine: Strategies and Best Practices

Currently, I am in the process of creating a series of end-to-end tests using Protractor and Jasmine. I began by writing the following test: describe('app login page', function() { it('should be redirected to /#/login', function() { ...

Transferring data from a JavaScript variable to PHP using AJAX

I’m currently working through the tutorial at http://www.w3schools.com/php/php_ajax_database.asp and I think I have a good grasp of how it all operates. This is my code: PHP: <?php include('./db.php'); $PM = mysqli_query($con, "SELECT DIS ...

Developing asynchronous DOM functions for optimal performance

Imagine having a large amount of data that needs to be processed. In this scenario, the processing must happen on the client side rather than the server side. The data processing involves iterating through each element in the data set: for element in data ...

What is preventing my for loop from reaching the initial index in this visually distinct nested array pattern?

Struggling with rearranging letters in a W shape using arrays. My code seemed to go down instead of reaching level 0. Code snippet: const row = totalLevel =>{ let array = [] for(let i =0;i<totalLevel;i++){ array.push([]) } r ...

Identifying and capturing changes in child scope events or properties in Angular

I am encountering an issue with my form directive where I need to intercept ng-click events nested within varying child scopes of the form element. However, I am struggling to hook into these events or child scope properties in a generic way. For demonstr ...

What is the process for integrating a popup component into a React-Native application?

As a React-Native beginner, I wanted to incorporate a popup window into my app. After some research, I came across this solution: https://www.npmjs.com/package/react-native-popup I followed the first step: npm install react-native-popup --save However, w ...

When using NodeJS and MongoDB together, a POST request may receive a 404 error code

Despite having all the routes set up correctly, I'm encountering a 404 error when trying to send a POST request. I've searched through numerous similar questions but haven't come across a solution that addresses my specific issue. Below is ...

Sending data from Django's render() method to React.js

Currently, I'm working on a Django + React Application project where I am faced with the challenge of passing JSON data from Django's render() function to React.js. To achieve this, I initiate the rendering of an HTML page using Django, with the ...

AngularJS: Utilizing services to make API requests and retrieve JSON data

I am struggling to pass a value from an input field on the view using a service. The service is supposed to call my WebAPI2 and then receive a valid JSON as a response. Unfortunately, I keep getting a promise object that I cannot resolve (even with ".then ...

The JavaScript array created from parsing JSON returns a value of undefined

Once again, the gecko scenario! The JSON used in this script to fill a listbox has been validated by JSONLint. The code snippet below demonstrates how the parsed data is placed in arrays: pdata = jQuery.parseJSON(data); ctype = pdata[0]; stype = pdata[1]; ...