Logging out of an AngularJs Single Page Application

I recently asked a more complex question on Stack Overflow regarding AngularJS logout action. However, I have another aspect that I believe warrants a separate question.

In my Angular SPA, I have implemented authentication using bearer JWT tokens. I utilize ng-route to navigate between different views. For example, one view (/protected route, protectedController and protectedDataService) contains protected resources, while another view (/unprotected route, unprotectedController and unprotectedDataService) contains unprotected resources. Below are sample code snippets for the controllers:

(function () {
    'use strict';

    angular
        .module('protectedCtrl',[])
        .controller('protectedController', ['$location','protectedDataService', function ($location, protectedDataService) {
            var vm = this;
            vm.title = 'protectedController';
            protectedDataService.getData().then(function (res) {
                vm.values = res.data;
            }, function (err) {
                console.log(err);
            });
        }]);
})();

Unprotected controller:

(function () {
    'use strict';

    angular
        .module('unprotectedCtrl',[])
        .controller('unprotectedController', ['$location','unprotectedDataService', function ($location, unprotectedDataService) {
            var vm = this;
            vm.title = 'unprotectedController';
            unprotectedDataService.getData().then(function (res) {
                vm.values = res.data;
            }, function (err) {
                console.log(err);
            });
        }]);
})();

If an unauthenticated user tries to access a protected resource (/protected path), they will be redirected to the login page. However, in the scenario where a logged-in user clicks the logout button (for now manually deleting token info from local storage and reloading the page), how can I handle the redirection based on the active page? Specifically, if the user is on the /protected page, they should be redirected to the login page. If they are on the /unprotected page, no action should be taken. How can I determine which page is active in ng-view (requires auth or not) and make a decision about redirection?

Answer №1

If you want to monitor route changes and decide whether to redirect to a login page or not, you can utilize the $routeChangeStart event along with a helper function.

Within the run block of your Angular app, you can define a list of routes that do not require authentication and create a function to determine if the upcoming route is in this list.

angular
  .module('awesomeApp')
  .run(function (/* inject dependencies */) {
    // other code

    var routesThatDoNotRequireAuthentication = ['/unprotected'];

    function isRouteSafe(route, availableRoutes) {
      var routeFound = false;
      for (var i = 0; i < availableRoutes.length; i++) {
        routeFound = routeFound || route.indexOf(availableRoutes[i]) > -1;
      }
      return routeFound;
    }

    $rootScope.$on('$routeChangeStart', function () {
      var isAuthenticated = authenticationService.isAuthenticated();
      var newRoute = $location.url();

      if (!isRouteSafe(newRoute, routesThatDoNotRequireAuthentication) && !isAuthenticated) {
        $location.path('/login');
      }
    });
});

Update

If not all your routes are prefixed with '/protected' or '/unprotected', you can add a property when setting up routes using $routeProvider:

$routeProvider
  .when('/awesomePath', {
    templateUrl: 'awesome-template.html',
    controller: 'AwesomeController',
    controllerAs: 'vm',
    requireAuth: true  
  })

In the $routeChangeStart handler, you can then check if the user is accessing a protected route:

$rootScope.$on('$routeChangeStart', function () {
      var isAuthenticated = authenticationService.isAuthenticated();
      var newRoute = $location.url();

      if ($route.routes[$location.url()].requireAuth && !isAuthenticated) {
        $location.path('/login');
      }
    });

This approach allows for more flexibility without hardcoding the routes.

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

Replace the arrow and implement collapsible div using CSS

My HTML code has the following structure: <ul id="urlcss"> <li class="nav-submenu"> <a class="collapsed" href="#" data-toggle="collapse" data-target="#submenu0"> ...

Modify an element on one webpage using a function called from another webpage

I am currently working on a website design that involves displaying images on various frames. While I have managed to change content across different frames, I am now exploring the possibility of changing content across different web pages. Here is the se ...

Issue with accessing this.props when using withStyles and React Router in React Material UI

When it comes to accessing { classes }, the behavior differs between the Parent Component and the Child Component. In the Parent Component, this.props is defined and can locate { classes } without any issues. However, in the Child Component, this.props app ...

Is it feasible to use PHP code within a Javascript environment?

Looking for help with integrating PHP code into a JavaScript script: var bigData = { "teams" : [], "results" : [] }; for( var i=1 ; i<16 ; i+=2 ) { bigData.teams.push(["<?php echo 1; ?>",'Team '+(i+1)]); } for( var j=1 ; j& ...

JavaScript tri-state toggling

After devising 2 buttons, each intended to toggle a heading or paragraph, I encountered a slight issue. When using the 'Toggle Para' button, the switch occurs between 2 paragraphs upon 2 clicks. However, on the third click, I desire for both para ...

Executing NestJS code after applying a pipe but before reaching the method handler

Is it possible to insert additional code after all the pipes have transformed but before the method handler is called? https://i.sstatic.net/IjQvv.png ...

What is the best way to show the user profile on a Forum?

I am struggling to figure out how to display the username of a user on my forum page. I currently only have access to the user's ID and need help in extracting their name instead. It seems that I lack knowledge about mongoose and could really benefit ...

Rejuvenate your Bootstrap Accordion with these Settings

Using bootstrap documentation, I have implemented an accordion in my web application with the following code: <div class="accordion" id="accordion2"> <div class="accordion-group"> <div class="accordion-heading"> <a class=" ...

Why doesn't Material-UI seem to understand the theme.spacing function?

Issue with Material-UI's theme.spacing function I've encountered a problem while using Material-UI's theme.spacing function in a React application. It seems that the spacing function is not being recognized. The Javascript error message st ...

Sending multiple HTTP requests sequentially

I've been attempting to send a request object to a server repeatedly in a loop, aiming to execute the task 1000 times. The scenario is reminiscent of the movie Office Space, where a small sum is extracted from numerous bank accounts. Here's the ...

Controlling the Escape Key and Clicking Outside the Material-ui Dialog Box

I am currently utilizing material-ui's dialog feature. In this setup, when a user clicks the "sign out" button, a dialog box opens with options to either confirm the sign out by selecting "yes" or cancel it by choosing "no". The issue arises when the ...

Record changes in another sheet when Google Spreadsheet is edited

Can anyone provide assistance with a problem in Google Spreadsheet? I am looking to log the name and timestamp when a value in a specific column in the "Venues" sheet is changed. However, I'm having trouble determining if I'm working with the co ...

Your request must be a POST method and only absolute URLs are allowed

I have created a client-side app.js file that makes a post request to a server (code provided below): const fetch = require('node-fetch'); /* Function for POSTing data */ const postData = async ( url = 'http://localhost/8000/add ...

Ways to change object to string in javascript

My object has the following structure: Object {Dry Aged Ribeye(medium): "1" , Dry Aged Ribeye(rare): "1" , Dry Aged Ribeye(well): "1" , favorite_tables: "{"dc76e9f0c0006e8f919e0c515c66dbba3982f785":[]}" } I am trying to insert this into My ...

Issue occurred while attempting to access the $modal service within the run block

Using the ui-bootstrap modal in my main module for login authentication is causing an error when calling the loginModal service from the run block. TypeError: loginModal is not a function angular.module('myApp', ['ui.router', &apos ...

Scrapy-splash seems to be encountering difficulties in extracting elements during the scraping process

My attempt to extract data from this Why is Splash not working here? Does anyone have a solution for me? Your assistance will be highly appreciated! ...

The RGB values of a dynamically loaded image being drawn to a canvas in JavaScript are slightly off

After hosting some .PNG images on my NGINX webserver, I noticed a discrepancy in the RGB values when loading and drawing them on a canvas using context.drawImage(img, 0, 0); and retrieving the image data using context.getImageData(x, y, 1, 1).data. Interes ...

Create a custom VueJS component by utilizing an npm package

Looking to navigate around X-frame restrictions? You can check out this npm package: https://www.npmjs.com/package/x-frame-bypass To make it work, include the following tag within your HTML: <iframe is="x-frame-bypass" src="https://example.org/">& ...

Error: There was an unexpected token found in the $http.get() request syntax

When attempting to create my first Angular app, I encountered the following error Here is the JavaScript code snippet: var app = angular.module('sortApp', []) app.controller('sortController', ['$http', function ($http) { ...

"Exploring the world of Sharepoint Online WebParts with a touch

Recently, I decided to migrate a website that I previously built in SharePoint 2013 to be a Sharepoint Online WebPart. After doing some research, it seems like WebParts are typically created using TypeScript. Is TypeScript really the only way to go about b ...