How to achieve a Safe (!) authentication system in an angularjs app?
Solution 1:
You cannot authorize anything in angularjs, because the user has full controll of the execution environment (namely, the browser). Each check, case, if - anything you can think of - can be tampered with. There are javascript libraries that use asymmetric keys to perform local encryption to store local data somewhat safely, but they are not what you are looking for, really.
You can, and you should, authorize things on the server - the standard way you would do it in an ordinary application - using session; no special code is necessary, ajax calls use ordinary session cookies. Application does not need to know whether it's authenticated or not. It only needs to check what server thinks.
From the perspective of your angularjs application, being "logged in" or "logged out" is merely a gui hint for the user.
Solution 2:
Probably you found a solution, but currently I made up an authenticaiton scheme I'm implementing in my Angular App.
On .run the app is registered with an ActiveSession set to false. It then checks if the browser has a cookie with a token and a userId.
If YES, check token+userId on server and updates the token on both server and local (token it's a server generated key unique for each user)
If NO shows login form, check credentials and again if they are valid does a server request t get a new token and saves is locally.
The token is used to make a persistent login (remember me for 3 weeks) or when user refreshes the browser page.
Thank you
Solution 3:
I asked this question three months ago.
I would like to share what has become my favourite approach when I've to deal with user authentication in a web app built over AngularJS.
Of course fdreger's answer is still a great answer!
You cannot authorize anything in angularjs, because the user has full controll of the execution environment (namely, the browser).
From the perspective of your angularjs application, being "logged in" or "logged out" is merely a gui hint for the user.
So, briefly my approach consists in:
1) Bind to each route additional information about the route itself.
$routeProvider.when('/login', {
templateUrl: 'partials/login.html', controller: 'loginCtrl', isFree: true
});
2) Use a service to mantain the data about each user, and their authentication status.
services.factory('User', [function() {
return {
isLogged: false,
username: ''
};
}]);
3) Everytime the user try to access a new route, check if they have the grant to access.
$root.$on('$routeChangeStart', function(event, currRoute, prevRoute){
// prevRoute.isFree tell me if this route is available for all the users, or only for registered user.
// User.isLogged tell me if the user is logged
})
I also wrote about this approach (more in detail) on my blog, users authentication with angularjs.
Solution 4:
First of all: Client-side data can always be manipulated or tampered with.
As long as valid session IDs aren't easily guessable and measures like associating session tokens with the client's IP there is no big deal about it.
You could, in theory, also encrypt the cookie, as long as you do so on the server side.
For details on how to encrypt your cookies, see the docs of your server-side (e.g http://expressjs.com/api.html#res.cookie for Express.js)