Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS: Basic example to use authentication in Single Page Application

I am new to AngularJS and gone through their tutorial and got a feel for it.

I have a backend for my project ready where each of the REST endpoints needs to be authenticated.

What I want to do
a.) I want to have a single page for my project http://myproject.com.
b.) Once a user hits the URL in browser, based on if user is logged in or not, he is presented with a home page/view or login page/view under the same url http://myproject.com.
c.) if a user is not logged in, it fills out the form and server sets a USER_TOKEN in session, so all further requests to endpoints will be authenticated based on USER_TOKEN

My Confusions
a.) How can I handle client-side authentication using AngularJS? I saw here and here but did not understand how to use them
b.) How can I present different views to user based on if user is logged in or not under same url http://myproject.com

I am using angular.js for the very first time and really getting confused as to how to start. Any advices and/or resources are very much appreciated.

like image 967
daydreamer Avatar asked Apr 22 '13 04:04

daydreamer


People also ask

Can we use basic HTTP auth in AngularJS?

AngularJS Authentication ServiceThe Authentication Service is the interface between the angularjs app and the server side api, so http requests are managed here. It also contains a Base64 service for encoding the username and password to be used in the HTTP Authorization header for all requests after logging in.

What is authentication in AngularJS?

Authentication plays an important role in today's web applications. It is a process of accessing application or features by providing user's identity that helps the verifier in getting complete information about the user's activity. We can categorize the web-applications into 2 types – Public & Private.

How many $rootScope an AngularJS application can have * 1 point?

An app can have only one $rootScope which will be shared among all the components of an app.


2 Answers

I've created a github repo summing up this article basically: https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec

ng-login Github repo

Plunker

I'll try to explain as good as possible, hope I help some of you out there:

(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 {         // 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.

like image 175
Alex Arvanitidis Avatar answered Sep 22 '22 16:09

Alex Arvanitidis


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

like image 43
daydreamer Avatar answered Sep 18 '22 16:09

daydreamer