User authentication in MEAN Stack using passport-local and $routeProvider for routing

When it comes to logging users into my application, I am utilizing passport-local. The login process involves a function called in my AngularJS controller:

$http.post('/login', $scope.user).then(function (response){
    if(response.data.success){
        //Upon successful login, the user data is logged and they are redirected to the main page.
        console.log(response.data.user);
        $location.path(response.data.redirectTo);
    } else {
        // Handling error messages from Express routing.
    }
});

Currently, everything works fine as expected. Upon successfully entering correct credentials, the user's data is logged and they are redirected to a new page.

My concern now is ensuring that all other pages confirm whether or not the user has logged in. How should I handle the received user data? The other pages use the following $routeProvider routing configuration:

app.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/login', {
    templateUrl: 'login.html',
    controller: 'loginCtrl'
  });

  $routeProvider.when('/home', {
    templateUrl: 'home.html',
    controller: 'homeCtrl',
    // Implementing functionality to validate user login status
  });

}])

All the tutorials I consulted suggest handling this via Express routing, but doing so results in a redirect loop due to /login omitting the isAuthenticated middleware check.

app.get('*', isAuthenticated, function(req,res){
    res.sendFile("index.html");
});

function isAuthenticated(req,res,next){
    if(req.isAuthenticated()){
        next();
    } else {
        res.redirect('/login');
    }
}

I would greatly appreciate any guidance on how to proceed from here.

Answer №1

To ensure that your angularJs app can detect when a login is required, you will need to create an interceptor for handling responses from your express app. Instead of redirecting to /login within your express app, it's best practice to allow your angularJs app to handle the routing. Your express app should simply send json resources or return a 401 Status Code Response to indicate that the request is unauthorized.

When your angularJs interceptor detects unauthorized headers, it can prompt the user with a login page:

app.config(function($httpProvider) {

    // Configure $http to display a login dialog upon receiving a 401 unauthorized response
    $httpProvider.responseInterceptors.push(
            function($rootScope, $q, $location) {

                return function(promise) {
                    return promise.then(
                            // Success - don't intercept           
                            function(response) {
                                return response;
                            },
                            // Error - if 401 save the request and broadcast an event
                                    function(response) {
                                if (response.status === 403 || response.status === 401) {
                                            var deferred = $q.defer(),
                                                    req = {
                                                        path: $location.path(),
                                                        config: response.config,
                                                        deferred: deferred
                                                    };
                                            $rootScope.requests401.push(req);
                                            $rootScope.$broadcast('event:loginRequired');
                                            return deferred.promise;
                                        }
                                        return $q.reject(response);
                                    }
                            );
                        };
            });
         });            
app.run(function($rootScope, $http, $location, base64) {


/**
 * Holds all the requests which failed due to 401 response.
 */
$rootScope.requests401 = [];

$rootScope.$on('event:loginRequired', function() {
    $location.path('/login');
});

/**
 * On 'event:loginConfirmed', resend all the 401 requests.
 */
$rootScope.$on('event:loginConfirmed', function(){

    var i, requests = $rootScope.requests401,
            retry = function(req) {
                $http(req.config).then(function(response) {
                    req.deferred.resolve(response);
                });
            };

        });
});

In addition, your LoginCtrl needs to emit the loginConfirmed event. Once the user logs in successfully, you can store their details in the root scope for future access.

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

Is it possible to iterate through HTML form data using JSON arrays or objects?

I've been searching this website and the internet for a while now, trying to figure out how to save multiple arrays to my localStorage. I asked a question earlier which helped me progress a bit, but I'm still struggling to grasp the concept. I c ...

The current context for type 'this' cannot be assigned to the method's 'this' of type '...'

Currently, I am in the process of defining type definitions (.d.ts) for a JavaScript library. In this specific library, one of the methods accepts an object of functions as input, internally utilizes Function.prototype.bind on each function, and then expos ...

"Troubleshooting async/await issue with Node.js Sequelize and configuring the connection

function credential(secretFromVault) { const creddetails = new ClientSecretCredential(clientId, tenantId, clientSecret); // Build the URL to reach your key vault const url = `https://<vaultName>.vault.azure.net/`; // Lastly, create our secre ...

What is the best way to retrieve router parameters within a JSX component?

How can I pass the post ID as a prop to the EditPost component in order to edit it? render() { return ( <Router> <Switch > <Route path="/edit/:id"> <EditPost index={/*what do I do here?*/} /> ...

Tips on enabling JS tooltips in Shadow DOM

I am currently developing an app using Vue and Bootstrap, where I am creating web components based on the official Vue documentation. The Bootstrap framework and my business logic are functioning well within the #shadow-root of the web components, behaving ...

Which type of element does Youtube utilize for the videos on its own domain - <iframe> or <video>?

Do they have a different method for incorporating their videos? My goal is to utilize the playbackRate property on a non-embedded YouTube video for a Chrome extension. ...

Verifying password authenticity using AngularJS

Hi there! I'm currently troubleshooting some code that is meant to validate passwords with specific requirements, such as having a certain length and containing special characters. I've managed to set the correct password length, but I'm en ...

Error on line 192 in _http_server.js: RangeError thrown due to an invalid status code (${statusCode})

Below is the code I have written: var express = require('express'); var http = require('http'); var redis = require('redis'); var url = require('url'); var client = redis.createClient().setMaxListeners(0); var app ...

Styling with CSS Variables and Transforming Elements

After conducting thorough research both on this platform and via Google, I have yet to find a solution to my query: "how can CSS variables be utilized in a CSS transform?" Within the HTML header, three CSS variables and their fallback values are declared: ...

What could be causing my ajax request to not be successfully compiled?

I seem to be experiencing an issue with this part of my code. Despite trying multiple methods, it still isn't functioning correctly. What steps can I take to resolve this problem? $.ajax({ url: "https://corona-api.com/countries/BR", ...

Stopping the loop: Disabling the SetInterval function with ResponsiveVoice code in JavaScript

Currently, I am developing a queuing system and implementing voice announcements using Responsive Voice. I have used setInterval, but the issue is that the voice keeps looping without stopping. $( document ).ready(function() { setInterval(function() ...

Trouble with $http response not appearing in AngularJS application

Currently, I am in the process of developing an angularjs application and encountering a challenging issue with setting up the $http connection to a php file. The header is displaying a response that I echoed from php. Nevertheless, two key problems persis ...

What is the best way to start tiny-slider automatically once the video has ended?

I am currently using the tns-slider plugin and have a setup with 3 slides (2 photos and 1 video). <div class='tiny-slider'> <div class='slide slide1'> <div class='video-slide'> <video id=&qu ...

Encountering a minimatch problem during the ionic installation process

I recently installed nodejs version 7.3.0 and encountered an error while trying to install Ionic using the CLI: npm WARN deprecated [email protected]: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue After researching, I foun ...

React is failing to display identical values for each item being mapped in the same sequence

I have implemented some standard mapping logic. {MEMBERSHIPS.map((mItem, index) => ( <TableCell className="text-uppercase text-center" colSpan={2} padding="dense" ...

Ways to retrieve a JSON element and incorporate it into a CSS styling

Can someone assist me in converting a JSON object for use in CSS? I've attempted to do this using Vue.js, creating a map legend with v-for to generate the legend. However, if there is an alternative method that allows me to take a JSON object and ins ...

Issues arise when attempting to transfer strings through ajax to a Node.js server that is utilizing express.js

On my website, I am encountering a problem where certain characters are being lost when I send strings to my Node.js server. // Client: microAjax("/foo?test="+encodeURI("this is ++ a test"), function callback(){}); // Server: app.get('/foo',fun ...

Guide on navigating an array of objects using the provided keys as a starting point in Javascript/Typescript

Assuming I have an array of objects structured like this: const events: Array<{year: number, month: number, date: number}> = [ {year: 2020, month: 10, date: 13}, {year: 2021: month: 3, date: 12}, {year: 2021: month: 9, date: 6}, {year: 2021: mont ...

Selecting the events that I want my directives to track

Here is a directive example: 'use strict'; angular.module('epw') .directive('md-title', function ($rootScope) { return { scope: { listenTo: '@' }, controller: function () { $ ...

Configuring a devServer proxy leads to a 404 error

Within my src/vue.config.js file, I have the following configuration: module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:8081', changeOrigin: true, }, }, }, }; When I c ...