Well, I used this approach (according to Frederick Naqstad), and so far this is normal.
Authentication is pretty simple. The user submits credentials via an encrypted connection through the form:
<form name="loginform" class="uk-form" ng-submit="login()"> <fieldset data-uk-margin> <legend><h2>Login</h2></legend> <div class="uk-form-row"> <input class="uk-form-large" type="text" ng-model="cred.user" placeholder="Username" required> </div> <div class="uk-form-row"> <input class="uk-form-large" type="password" ng-model="cred.password" placeholder="Password" required> </div> <div class="uk-form-row"> <button ng-disabled="loginform.$invalid" class="uk-button uk-button-large" type="submit">Login</button> </div> </fieldset> </form>
The controller then processes the response as follows:
App.controller('LoginCtrl', function ($rootScope, $scope, $location, $window, authService) { $scope.cred = {} $scope.login = function () { if ($scope.loginform.$valid) { authService.auth(this.cred, function (stat) { if (stat === 200) { $rootScope.loginStatus = authService.isLoggedIn(); $location.path('/test'); } else { .... $location.path('/login'); } }); $scope.cred = {} $scope.loginform.$setPristine(); } }; $window.document.title = 'Admin Login'; });
The controller expects a 200 http status code (which the server should not respond if authentication is not successful), if the server responds with something other than 200, the route changes again to the login page.
The tricky part is checking the authentication status check.
The way I implemented my authentication system is to add user attributes to the route object (for example, a guide, but without a role system) as follows:
App.js
... $routeProvider.when('/login', { templateUrl: '/content/...', controller: 'Ctrl1', requireLogin: false }).when('/logout', { resolve: { logout: function ($location, $rootScope, authService) { authService.logout(function (s) { if (s === 200) { $rootScope.loginStatus = authService.isLoggedIn(); $location.path('/test'); } else { .... } }); } }, requireLogin: true }).when('/metaconfig', { templateUrl: '/content/...', controller: 'Ctrl2', requireLogin: true ...
Then whenever a route is requested, I have this function that evaluates whether a route requires certain privileges / authentication on that route or not (ofc this does not mean that your route is protected, it just means that your average joe wont have the ability to view routes if js files do not change on the fly)
App.js
angular.module('App', ['ngCookies', 'ngRoute']) .config(function{...}).run(function ($rootScope, ..., $location, authService) { $rootScope.loginStatus = false; authService.authCheck(); $rootScope.$on('$routeChangeStart', function (event, next, current) { if (next.requireLogin) { if (!authService.isLoggedIn()) { $location.path('/login'); event.preventDefault(); } } });
The function passed with $routeChangeStart calls another function inside the service, which I called authService , and looks like this:
authService.js
'use strict'; App.service('authService', function ($rootScope, $log, $http, $q) { var userIsAuthenticated = false; this.auth = function (up, cb) { $http({method: 'POST', url: '/api/login', data: up}). success(function (data, status, headers, config) { if (status === 200) { userIsAuthenticated = true; } cb(status) }). error(function (data, status, headers, config) { userIsAuthenticated = false; cb(status) }); }; this.authCheck = function () { $http({method: 'PUT', url: '/api/login' }). success(function (data, status, headers, config) { if (status === 200) { userIsAuthenticated = true; } else { userIsAuthenticated = false; } $rootScope.loginStatus = userIsAuthenticated; }). error(function (data, status, headers, config) { userIsAuthenticated = false; $rootScope.loginStatus = userIsAuthenticated; }); }; this.isLoggedIn = function () { return userIsAuthenticated; }; this.logout = function (cb) { $http({ method: 'DELETE', url: '/api/logout' }). success(function (data, status, headers, config) { userIsAuthenticated = false; cb(status) }). error(function (data, status, headers, config) { userIsAuthenticated = false; cb(status) }); }; });
Now, every time a route requiring a certain role or authentication will have to evaluate and receive a status code 200 from the server, otherwise the authentication status will be false until the user is authenticated again. Finally, relying on your interface, even 1% of the authorization process, the system will be completely redundant.
Edit
CSRF Risk and Session Management
In the case of CSRF, I use a framework called Beego , this structure offers a mechanism to prevent CSRF from the box, where you just need to specify the expiration date and token encryption.
When it comes to login sessions, the server must manage the encrypted sessions, which are stored as cookies on the client side, of course, I do not recommend you implement this, because it is very risky and may be implemented incorrectly. Again, Beego offers a nice feature that allows you to manage and encrypt sessions in your own way.
Hope this helps answer your question, good luck.