GithubHelp home page GithubHelp logo

alarv / ng-login Goto Github PK

View Code? Open in Web Editor NEW
91.0 13.0 33.0 199 KB

Login/Authentication/Authorization logic on an AngularJS application

Home Page: http://plnkr.co/edit/Mvrte4

License: MIT License

JavaScript 60.97% CSS 0.17% HTML 38.86%

ng-login's Introduction

ng-login

Plunker: http://plnkr.co/edit/Mvrte4

This code was created to sum all authentication suggestions I gathered from my research. I also added the $modal service of UI Bootstrap, for the login procedure to be smoother for the end-user. A login/authentication logic on an Angular JS application is provided, along with authorization per route given some user roles. It is mainly based on those 3 articles (mostly the 1st), with my addition of a modal login window, using the UI Bootstrap $modal service:

  1. https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec

  2. http://www.sitepoint.com/implementing-authentication-angular-applications/

  3. http://www.frederiknakstad.com/2013/01/21/authentication-in-single-page-applications-with-angular-js/

To store the data locally for the user to be able to refresh the page I use $window.sessionStorage, which is provided by every browser(even IE9!) and is erased when the browser is closed. Logic goes like this:

(1) app.js: Creation of authentication constants on app definition

var loginApp = angular.module('loginApp', ['ui.router', 'ui.bootstrap'])
/*Constants regarding user login defined here*/
.constant('USER_ROLES', {
	all : '*',
	admin : 'admin',
	editor : 'editor',
	guest : 'guest'
}).constant('AUTH_EVENTS', {
	loginSuccess : 'auth-login-success',
	loginFailed : 'auth-login-failed',
	logoutSuccess : 'auth-logout-success',
	sessionTimeout : 'auth-session-timeout',
	notAuthenticated : 'auth-not-authenticated',
	notAuthorized : 'auth-not-authorized'
})

(2) Auth Service: All following functions are implemented in auth.js service. The $http service is used to communicate with the server for the authentication procedures. Also contains functions on authorization, that is if the user is allowed to perform a certain action.

angular.module('loginApp')
.factory('Auth', [ '$http', '$rootScope', '$window', 'Session', 'AUTH_EVENTS', 
function($http, $rootScope, $window, Session, AUTH_EVENTS) {

authService.login() = [...]
authService.isAuthenticated() = [...]
authService.isAuthorized() = [...]
authService.logout() = [...]

return authService;
} ]);

(3) Session: A singleton to keep user data. The implementation here depends on you.

angular.module('loginApp').service('Session', function($rootScope, USER_ROLES) {

	this.create = function(user) {
		this.user = user;
		this.userRole = user.userRole;
	};
	this.destroy = function() {
		this.user = null;
		this.userRole = null;
	};
	return this;
});

(4) Parent controller: Consider this as the "main" function of your application, all controllers inherit from this controller, and it's the backbone of the authentication of this app.

<body ng-controller="ParentController">
[...]
</body>

(5) Access control: To deny access on certain routes 2 steps have to be implemented:

a) Add data of the roles allowed to access each route, on ui router's $stateProvider service as can be seen below (same can work for ngRoute).

.config(function ($stateProvider, USER_ROLES) {
  $stateProvider.state('dashboard', {
    url: '/dashboard',
    templateUrl: 'dashboard/index.html',
    data: {
      authorizedRoles: [USER_ROLES.admin, USER_ROLES.editor]
    }
  });
})

b) On $rootScope.$on('$stateChangeStart') add the function to prevent state change if the user is not authorized.

$rootScope.$on('$stateChangeStart', function (event, next) {
    var authorizedRoles = next.data.authorizedRoles;
    if (!Auth.isAuthorized(authorizedRoles)) {
      event.preventDefault();
      if (Auth.isAuthenticated()) {
        // user is not allowed
        $rootScope.$broadcast(AUTH_EVENTS.notAuthorized);
      } else {d
        // user is not logged in
        $rootScope.$broadcast(AUTH_EVENTS.notAuthenticated);
      }
    }
});

(6) Auth interceptor: This is implemented, but can't be checked on the scope of this code. After each $http request, this interceptor checks the status code, if one of the below is returned, then it broadcasts an event to force the user to log-in again.

angular.module('loginApp')
.factory('AuthInterceptor', [ '$rootScope', '$q', 'Session', 'AUTH_EVENTS',
function($rootScope, $q, Session, AUTH_EVENTS) {
	return {
		responseError : function(response) {
			$rootScope.$broadcast({
				401 : AUTH_EVENTS.notAuthenticated,
				403 : AUTH_EVENTS.notAuthorized,
				419 : AUTH_EVENTS.sessionTimeout,
				440 : AUTH_EVENTS.sessionTimeout
			}[response.status], response);
			return $q.reject(response);
		}
	};
} ]);

P.S. A bug with the form data autofill as stated on the 1st article can be easily avoided by adding the directive that is included in directives.js.

P.S.2 This code can be easily tweaked by the user, to allow different routes to be seen, or display content that was not meant to be displayed. The logic MUST be implemented server-side, this is just a way to show things properly on your ng-app.

ng-login's People

Contributors

alarv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ng-login's Issues

Is there a way to persist user not using browser storage?

Hi alarv, first of all, thanks for the tutorial. I've been reading it for a few days trying to understand the flow of data, and I think I got it.

There's one nagging thing I'm dealing with. I can currently login into my backend and I can also logout.
However, if I refresh the application at any moment, user data is deleted and I'm redirected to my login form. I'm not using the Session singleton, I'm just storing my user credentials in $rootScope.

Shouldn't that data be persisted throughout the entire application?

login page on a separate page

It's amazing and it works great, thanks for sharing.
I have a couple of questions, in my application I have a login page on a separate page, and not in a modal window, I would like to know that information would go into it (page logon) to be able to login from it.
for example:

.state('login', {
      url: "/login",
      templateUrl: "templates/login.html",
      data: {
          authorizedRoles: [USER_ROLES.loginpage]
      }
    })

ย 
Apologies for the translation, use Google Translate

Use of $rootScope to contain currentUser

Thank you for this excellent piece of angular code. This is probably not an issue, but the parentController has the function

var setCurrentUser = function(){
    $scope.currentUser = $rootScope.currentUser;
}

Isn't enclosing the page contents in a parentController exactly for the specific reason of avoiding use of $rootScope (other than listeners)?

parentcontroller issue

I have followed your example, but i do have some issues loading the parent controller. Can you please explain what do you mean with:

// this is the parent controller for all controllers.
// Manages auth login functions and each controller
// inherits from this controller

before adding authentication to my app, in index.html i only had to add ng-app="myApp" to the body tag and all worked well. now, when i'm trying to add ng-controller="ParentController" nothing shows up in my app, except the header, and the login modal doesn't popup no matter what menu i choose.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.