AngularJS- Login and Authentication in each route and controller
My solution breaks down in 3 parts: the state of the user is stored in a service, in the run method you watch when the route changes and you check if the user is allowed to access the requested page, in your main controller you watch if the state of the user change.
app.run(['$rootScope', '$location', 'Auth', function ($rootScope, $location, Auth) {
$rootScope.$on('$routeChangeStart', function (event) {
if (!Auth.isLoggedIn()) {
console.log('DENY');
event.preventDefault();
$location.path('/login');
}
else {
console.log('ALLOW');
$location.path('/home');
}
});
}]);
You should create a service (I will name it Auth
) which will handle the user object and have a method to know if the user is logged or not.
service:
.factory('Auth', function(){
var user;
return{
setUser : function(aUser){
user = aUser;
},
isLoggedIn : function(){
return(user)? user : false;
}
}
})
From your app.run
, you should listen the $routeChangeStart
event. When the route will change, it will check if the user is logged (the isLoggedIn
method should handle it). It won't load the requested route if the user is not logged and it will redirect the user to the right page (in your case login).
The loginController
should be used in your login page to handle login. It should just interract with the Auth
service and set the user as logged or not.
loginController:
.controller('loginCtrl', [ '$scope', 'Auth', function ($scope, Auth) {
//submit
$scope.login = function () {
// Ask to the server, do your job and THEN set the user
Auth.setUser(user); //Update the state of the user in the app
};
}])
From your main controller, you could listen if the user state change and react with a redirection.
.controller('mainCtrl', ['$scope', 'Auth', '$location', function ($scope, Auth, $location) {
$scope.$watch(Auth.isLoggedIn, function (value, oldValue) {
if(!value && oldValue) {
console.log("Disconnect");
$location.path('/login');
}
if(value) {
console.log("Connect");
//Do something when the user is connected
}
}, true);
AngularJs route authentication
As @SayusiAndo pointed out you need :
- http interceptor that will catch the 401 status, from you node server.
- and, then redirect the user to /login route if not logged in.
- Also, you should send your jwt token (that you should store), using the same interceptor.
Http interceptor :
app.factory('AuthInterceptor', function ($window, $q) {
return {
request: function(config) {
var token = $window.localStorage.getItem('token');
if(token){
config.headers.Authorization = 'Bearer ' + token;
}
return config;
},
response: function(response) {
if (response.status === 401) {
// redirect to login.
}
return response || $q.when(response);
}
};
});
// Register the AuthInterceptor.
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('AuthInterceptor');
});
Is there any other way to authentication the login page and route
You should include ng-view
in html to use different routes
Here I have updated your plunker https://plnkr.co/edit/7L6A6niKMQ4vn2OYP3LN?p=preview
You don't have some files which you are using in routes, I have change your home page for testing please update with yours
How do I check for login or other status before launching a route in Angular with routeProvider?
As in my comments above, there are 3 different paths (plus the ability to use a directive if you want to control it from within html templates). I ended up following
https://midgetontoes.com/angularjs-check-user-login/
which essentially is as follows:
$routeProvider.when('/secure', {
templateUrl: '/secure.html',
controller: 'Secure',
resolve:{
loggedIn:onlyLoggedIn
}
});
And then onlyLoggedIn
:
var onlyLoggedIn = function ($location,$q,Auth) {
var deferred = $q.defer();
if (Auth.isLogin()) {
deferred.resolve();
} else {
deferred.reject();
$location.url('/login');
}
return deferred.promise;
};
Simple, works like a charm. If I ever need a directive, I will pull this piece into a service.
AngularJS | handle routing before they load
My solution was combining $locationChangeStart
and $routeChangeStart
:
$rootScope.$on('$locationChangeStart', function (event) {
//If login data not available, make sure we request for it
if($facebook.isConnected()==null) {
$facebook.getLoginStatus();
event.preventDefault();
return;
}
var next=parseRoute().$$route;
if(!Auth.loginCheck(next))
event.preventDefault();
});
I copied parseRoute()
from angular-route.js
to parse the given URL to route..
Then I build my login check handler(Auth.loginCheck
) in a way that if it fail it return false.
I also use $routeChangeStart
to handle $route.reload()
events, so now after every change within my authentication status I just do $route.reload()
:
$rootScope.$on('$routeChangeStart', function (event, next) {
Auth.loginCheck(next);
});
Finally I just make sure that this custom service is always will run by using simple run()
method.
Edit:
We now using ngAuth, a module we designed to solve that exact problem(based on the answer I gave here before).
At last, we developed a angular-module that solved this issue.. This module is based on the answer I published here before.
Due the requests here, we published a beta release that works now: http://github.com/GoDisco/ngAuth
Feel free to use it.
Redirect on all routes to login if not authenticated
The best way to do this is to set up a '$routeChangeStart' listener which checks an 'authProvider' service function to verify that there is a user logged in. In our 'app.js' or in a separate file:
angular.module('myApp')
.run(['$rootScope', '$location', 'authProvider', function ($rootScope, $location, authProvider) {
$rootScope.$on('$routeChangeStart', function (event) {
if (!authProvider.isLoggedIn()) {
console.log('DENY : Redirecting to Login');
event.preventDefault();
$location.path('/login');
}
else {
console.log('ALLOW');
}
});
}])
Then for our 'authProvider' service:
angular.module('myApp')
.factory('authProvider', function() {
var user;
return {
setUser : function(aUser){
user = aUser;
},
isLoggedIn : function(){
return(user)? user : false;
}
};
});
This solution was created from an answer here on stack overflow.
Thank you @MohammadAwwaad
AngularJS: Basic example to use authentication in Single Page Application
I like the approach and implemented it on server-side without doing any authentication related thing on front-end
My 'technique' on my latest app is.. the client doesn't care about
Auth. Every single thing in the app requires a login first, so the
server just always serves a login page unless an existing user is
detected in the session. If session.user is found, the server just
sends index.html. Bam :-o
Look for the comment by "Andrew Joslin".
https://groups.google.com/forum/?fromgroups=#!searchin/angular/authentication/angular/POXLTi_JUgg/VwStpoWCPUQJ
Related Topics
Set a Callback Function to a New Window in JavaScript
How Is It Possible for an Iframe to Access Its Parents Dom
Jquery: How to Listen for Dom Changes
How to Format Vuetify Data Table Date Column
Angular2 Router 2.0.0 Not Reloading Components When Same Url Loaded with Different Parameters
When Using Jquery On(), Why Use (Document) VS. the Element Itself
How to Listen/Detect Changes to an Input Value - When the Input Value Is Changed via JavaScript
How to Reach the Element Itself Inside Jquery's 'Val'
Addeventlistener with Ajax Not Working Well
How to Prevent an Http Request Just for a Favicon
HTML - How to Show Tooltip Only When Ellipsis Is Activated
How to Play a Notification Sound on Websites
Div Square, Width Size Based on 100% Height
Is There an Alternative Method to Use Onbeforeunload in Mobile Safari
How to Set HTML Content into an Iframe
How to Capitalize the First Letter of Each Word in a String Using JavaScript