AngularJS: comment gérer des authentifications sur une même page d'application ?

Pour réaliser ce type d'authentification avec AngularJS, il faut respecter plusieurs étapes.

Le framework JavaScript AngularJS permet de créer un grand nombre de types d'applications web. Il est possible de gérer par exemple l'authentification et l'affichage du site sur une seule page. Pour réaliser cette technique, il faut respecter plusieurs étapes. La première étape se situe dans le fichier app.js. Il faut définir les constantes d'authentification pour l'application :

var authentificationApp = angular.module
('authentificationApp', ['ui.router', 'ui.bootstrap'])
/*Les constantes gérant la connexion sont définies ici*/
.constant('USER_ROLES', {
 all : '*',
 admin : 'admin',
 utilisateur : 'utilisateur',
 invite : 'invite'
}).constant('AUTH_EVENTS', {
 connexionReussie : 'auth-connexion-reussie',
 connexionEchouee : 'auth-connnexion-echouee',
 deconnexionReussie : 'auth-deconnexion-reussie',
 sessionExpiree : 'auth-session-expiree',
 nonConnecte : 'auth-non-connecte',
 nonAutorise : 'auth-not-autorise'
})

Il faut ensuite développer le fichier auth.js. Ce service communique avec le serveur pour gérer les procédures d'authentification. Il indique également si l'utilisateur est autorisé ou non à exécuter des actions.

angular.module('authentificationApp')
.factory('Auth', [ '$http', '$rootScope', '$window', 
'Session', 'AUTH_EVENTS', 
 function($http, $rootScope, $window, Session, AUTH_EVENTS) {
 authService.connexion() = [...]
 authService.estConnecte() = [...]
 authService.estAutorise() = [...]
 authService.deconnexion() = [...]
 return authService;
} ]);

Les données concernant l'utilisateur sont stockées dans un singleton. C'est à vous d'implémenter sa structure selon les besoins pour votre application. Voici un exemple de singleton :

angular.module('loginApp').service('Session', function
($rootScope, USER_ROLES) {
 this.create = function(utilisateur) {
 this.utilisateur = utilisateur;
 this.roleUtilisateur = utilisateur.role;
 };
 this.destroy = function() {
 this.utilisateur = null;
 this.roleUtilisateur = null;
 };
 return this;
});

Créez ensuite un contrôleur parent. Ce contrôleur sera le cœur de votre application. Tous les autres contrôleurs hériteront de ce contrôleur. Ce sera le coeur de la gestion de l'authentification de l'application.

<body ng-controller="ParentController"><br>...<br></body>

La partie suivante est la gestion des accès dans l'application. Pour autoriser un utilisateur à accéder à une page, il faut utiliser le service $stateProvider :

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

Pour prévenir le changement d'état si l'utilisateur n'est pas autorisé, il faut créer une fonction dans le scope ($rootScope.$on('$stateChangeStart')) :

$rootScope.$on('$stateChangeStart', function (event, next) {
 var authorizedRoles = next.data.authorizedRoles;
 if (!Auth.isAuthorized(authorizedRoles)) {
 event.preventDefault();
 if (Auth.isAuthenticated()) {
 // L'utilisateur n'est pas autorisé
 $rootScope.$broadcast(AUTH_EVENTS.nonAutorise);
 } else {
 // L'utilisateur n'est pas connecté
 $rootScope.$broadcast(AUTH_EVENTS.nonConnecte);
 }
 }
});

La dernière étape est un script qui intercepte le code de retour de la page. Si le code de retour http de la page indique une erreur, le script force l'utilisateur à se reconnecter pour pouvoir accéder au contenu de la page.

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.nonConnecte,
 403 : AUTH_EVENTS.notAutorise,
 419 : AUTH_EVENTS.sessionExpiree,
 440 : AUTH_EVENTS.sessionExpiree
 }[response.status], response);
 return $q.reject(response);
 }
 };
} ]);

AngularJS