I have an AngularJS application created by using yeoman, grunt and bower.
I have a login page that has a controller that checks for authentication. If the credentials are correct I reroute to home page.
app.js
'use strict';
//Define Routing for app
angular.module('myApp', []).config(['$routeProvider', '$locationProvider',
function($routeProvider,$locationProvider) {
$routeProvider
.when('/login', {
templateUrl: 'login.html',
controller: 'LoginController'
})
.when('/register', {
templateUrl: 'register.html',
controller: 'RegisterController'
})
.when('/forgotPassword', {
templateUrl: 'forgotpassword.html',
controller: 'forgotController'
})
.when('/home', {
templateUrl: 'views/home.html',
controller: 'homeController'
})
.otherwise({
redirectTo: '/login'
});
// $locationProvider.html5Mode(true); //Remove the '#' from URL.
}]);
angular.module('myApp').factory("page", function($rootScope){
var page={};
var user={};
page.setPage=function(title,bodyClass){
$rootScope.pageTitle = title;
$rootScope.bodylayout=bodyClass;
};
page.setUser=function(user){
$rootScope.user=user;
}
return page;
});
LoginControler.js
'use strict';
angular.module('myApp').controller('LoginController', function($scope, $location, $window,page) {
page.setPage("Login","login-layout");
$scope.user = {};
$scope.loginUser=function()
{
var username=$scope.user.name;
var password=$scope.user.password;
if(username=="admin" && password=="admin123")
{
page.setUser($scope.user);
$location.path( "/home" );
}
else
{
$scope.message="Error";
$scope.messagecolor="alert alert-danger";
}
}
});
On the home page I have
<span class="user-info">
<small>Welcome,</small>
{{user.name}}
</span>
<span class="logout"><a href="" ng-click="logoutUser()">Logout</a></span>
In the loginController
, I check the login info and if it's successful, I set the user object in the service factory. I don't know whether this is correct or not.
What I need is, When the user is logged in, It sets some value in the user object so that all other pages can get that value.
Whenever any route changes happen, the controller should check if the user is logged in or not. If not, it should reroute to the login page. Also, if the user is already logged in and come back to the page, it should go to home page. The controller should also check the credentials on all of the routes.
I have heard about ng-cookies, but I don't know how to use them.
Many of the examples I saw were not very clear and they use some kind of access roles or something. I don't want that. I only want a login filter. Can someone give me some ideas?
Here is another possible solution, using the
resolve
attribute of the$stateProvider
or the$routeProvider
. Example with$stateProvider
:Access
resolves or rejects a promise depending on the current user rights:UserProfile
copies the current user properties, and implement the$hasRole
,$hasAnyRole
,$isAnonymous
and$isAuthenticated
methods logic (plus a$refresh
method, explained later):Auth
is in charge of requesting the server, to know the user profile (linked to an access token attached to the request for example):The server is expected to return such a JSON object when requesting
GET api/auth
:Finally, when
Access
rejects a promise, if usingui.router
, the$stateChangeError
event will be fired:If using
ngRoute
, the$routeChangeError
event will be fired:The user profile can also be accessed in the controllers:
UserProfile
then contains the properties returned by the server when requestingGET api/auth
:UserProfile
needs to be refreshed when a user signs in or out, so thatAccess
can handle the routes with the new user profile. You can either reload the whole page, or callUserProfile.$refresh()
. Example when signing in:All have suggested big solution why you are worrying of session on client side. I mean when state/url changes I suppose you are doing an ajax call to load the data for tempelate.
Now the ajax data is returned by server using any api. Now the point came into play , return standard return types using server according to logged in status of user. Check those return codes and process your request in controller. Note:- For controller which doesn't require an ajax call natively , you can call a blank request to server like this
server.location/api/checkSession.php
and this is checkSession.phpOn client side inside controller or through any service as shown in other answers
Note :- I will update more tomorrow or in future
I feel like this way is easiest, but perhaps it's just personal preference.
When you specify your login route (and any other anonymous routes; ex: /register, /logout, /refreshToken, etc.), add:
So, something like this:
You don't ever need to specify "allowAnonymous: false", if not present, it is assumed false, in the check. In an app where most URLs are force authenticated, this is less work. And safer; if you forget to add it to a new URL, the worst that can happen is an anonymous URL is protected. If you do it the other way, specifying "requireAuthentication: true", and you forget to add it to a URL, you are leaking a sensitive page to the public.
Then run this wherever you feel fits your code design best.
You can use
resolve
:And, the function of the resolve:
Firebase also has a method that helps you install an observer, I advise installing it inside a
.run
:For instance an application has two user called ap and auc. I am passing an extra property to each route and handling the routing based on the data i get in $routeChangeStart.
Try this:
app.js:
I wrote a post a few months back on how to set up user registration and login functionality with Angular, you can check it out at http://jasonwatmore.com/post/2015/03/10/AngularJS-User-Registration-and-Login-Example.aspx
I check if the user is logged in the
$locationChangeStart
event, here is my main app.js showing this: