diff --git a/Module.php b/Module.php
index 42734fb2537737226c8862521c0b4c387d22a29d..f422d0eb12dafc7a8c34f6a7eb22dbe8178f32ed 100644
--- a/Module.php
+++ b/Module.php
@@ -2,6 +2,7 @@
 
 namespace UnicaenAuth;
 
+use UnicaenAuth\Guard\PrivilegeController;
 use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
 use Zend\ModuleManager\Feature\ConfigProviderInterface;
 use Zend\ModuleManager\Feature\ServiceProviderInterface;
@@ -23,6 +24,8 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface
         return include __DIR__ . '/config/module.config.php';
     }
 
+
+
     /**
      *
      * @return array
@@ -42,26 +45,30 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface
         ];
     }
 
+
+
     /**
      * This method is called once the MVC bootstrapping is complete,
      * after the "loadModule.post" event, once $application->bootstrap() is called.
      *
      * @param EventInterface $e
+     *
      * @see BootstrapListenerInterface
      */
-    public function onBootstrap(\Zend\EventManager\EventInterface $e) /* @var \Zend\Mvc\MvcEvent $e */
+    public function onBootstrap(\Zend\EventManager\EventInterface $e)
+        /* @var \Zend\Mvc\MvcEvent $e */
     {
         $application = $e->getApplication();
         /* @var $services \Zend\ServiceManager\ServiceManager */
-        $services    = $application->getServiceManager();
+        $services = $application->getServiceManager();
 
         // transmission des ACL aux aides de vue de navigation
         try {
-            $authorizeService = $services->get('BjyAuthorize\Service\Authorize'); /* @var $authorizeService \BjyAuthorize\Service\Authorize */
+            $authorizeService = $services->get('BjyAuthorize\Service\Authorize');
+            /* @var $authorizeService \BjyAuthorize\Service\Authorize */
             \Zend\View\Helper\Navigation::setDefaultAcl($authorizeService->getAcl());
             \Zend\View\Helper\Navigation::setDefaultRole($authorizeService->getIdentity());
-        }
-        catch (\Zend\ServiceManager\Exception\ServiceNotFoundException $snfe) {
+        } catch (\Zend\ServiceManager\Exception\ServiceNotFoundException $snfe) {
             // pas de module BjyAuthorize : pas d'ACL
         }
 
@@ -75,21 +82,21 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface
             $router->addRoutes([
                 // remplace les routes existantes (cf. config du module)
                 'zfcuser' => [
-                    'type' => 'Literal',
-                    'priority' => 1000,
-                    'options' => [
-                        'route' => '/auth',
+                    'type'          => 'Literal',
+                    'priority'      => 1000,
+                    'options'       => [
+                        'route'    => '/auth',
                         'defaults' => [
                             'controller' => 'zfcuser',
                             'action'     => 'index',
                         ],
                     ],
                     'may_terminate' => true,
-                    'child_routes' => [
-                        'login' => [
-                            'type' => 'Literal',
+                    'child_routes'  => [
+                        'login'  => [
+                            'type'    => 'Literal',
                             'options' => [
-                                'route' => '/connexion',
+                                'route'    => '/connexion',
                                 'defaults' => [
                                     'controller' => 'zfcuser',
                                     'action'     => 'authenticate', // zappe l'action 'login'
@@ -97,9 +104,9 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface
                             ],
                         ],
                         'logout' => [
-                            'type' => 'Literal',
+                            'type'    => 'Literal',
                             'options' => [
-                                'route' => '/deconnexion',
+                                'route'    => '/deconnexion',
                                 'defaults' => [
                                     'controller' => 'zfcuser',
                                     'action'     => 'logout',
@@ -107,11 +114,13 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface
                             ],
                         ],
                     ],
-                ]
+                ],
             ]);
         }
     }
 
+
+
     /**
      *
      * @return array
@@ -122,14 +131,50 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface
         return [
             'factories' => [
                 // verrue pour forcer le label de l'identifiant qqsoit l'options 'auth_identity_fields'
-                'zfcuser_login_form' => function($sm) {
+                'zfcuser_login_form' => function ($sm) {
                     $options = $sm->get('zfcuser_module_options');
-                    $form = new \ZfcUser\Form\Login(null, $options);
+                    $form    = new \ZfcUser\Form\Login(null, $options);
                     $form->setInputFilter(new \ZfcUser\Form\LoginFilter($options));
                     $form->get('identity')->setLabel("Username");
+
                     return $form;
                 },
             ],
         ];
-      }
+    }
+
+
+
+    /**
+     * Retourne le menu de navigation (à placer où vous voulez)!!
+     *
+     * @return array
+     */
+    static public function getDroitsNavigation($label=null, $title=null)
+    {
+        if (!$label) $label = "Droits d'accès";
+        if (!$title) $title = "Gestion des droits d'accès";
+        return [
+            'label'    => $label,
+            'title'    => $title,
+            'route'    => 'droits',
+            'resource' => PrivilegeController::getResourceId('UnicaenAuth\Controller\Droits','index'),
+            'pages'    => [
+                'roles'      => [
+                    'label'      => "Rôles",
+                    'title'      => "Gestion des rôles",
+                    'route'      => 'droits/roles',
+                    'resource'   => PrivilegeController::getResourceId('UnicaenAuth\Controller\Droits','roles'),
+                    'withtarget' => true,
+                ],
+                'privileges' => [
+                    'label'      => "Privilèges",
+                    'title'      => "Gestion des privilèges",
+                    'route'      => 'droits/privileges',
+                    'resource'   => PrivilegeController::getResourceId('UnicaenAuth\Controller\Droits','privileges'),
+                    'withtarget' => true,
+                ],
+            ],
+        ];
+    }
 }
\ No newline at end of file
diff --git a/config/module.config.php b/config/module.config.php
index 6ad30f0423c92bb94ac59e78fc5125937a9981f2..d7d20d8c3031e7b0ba1de5521c953b83b1a0c70b 100644
--- a/config/module.config.php
+++ b/config/module.config.php
@@ -1,149 +1,185 @@
 <?php
+
+use UnicaenAuth\Provider\Privilege\Privileges;
+
 $settings = [
+    'entity_manager_name' => 'doctrine.entitymanager.orm_default', // nom du gestionnaire d'entités à utiliser
+
     /**
      * Fournisseurs d'identité.
      */
-    'identity_providers' => [
+    'identity_providers'  => [
         300 => 'UnicaenAuth\Provider\Identity\Basic', // en 1er
         200 => 'UnicaenAuth\Provider\Identity\Db',    // en 2e
-        100 => 'UnicaenAuth\Provider\Identity\Ldap',  // en 3e
-    ],
-];
-
-$zfcuserSettings = [
-    /**
-     * Enable registration
-     * Allows users to register through the website.
-     * Accepted values: boolean true or false
-     */
-    'enable_registration'     => true,
-    /**
-     * Modes for authentication identity match
-     * Specify the allowable identity modes, in the order they should be
-     * checked by the Authentication plugin.
-     * Default value: array containing 'email'
-     * Accepted values: array containing one or more of: email, username
-     */
-    'auth_identity_fields'    => ['username', 'email'],
-    /**
-     * Login Redirect Route
-     * Upon successful login the user will be redirected to the entered route
-     * Default value: 'zfcuser'
-     * Accepted values: A valid route name within your application
-     */
-    'login_redirect_route'    => 'home',
-    /**
-     * Logout Redirect Route
-     * Upon logging out the user will be redirected to the enterd route
-     * Default value: 'zfcuser/login'
-     * Accepted values: A valid route name within your application
-     */
-    'logout_redirect_route'   => 'home',
-    /**
-     * Enable Username
-     * Enables username field on the registration form, and allows users to log
-     * in using their username OR email address. Default is false.
-     * Accepted values: boolean true or false
-     */
-    'enable_username'         => false,
-    /**
-     * Enable Display Name
-     * Enables a display name field on the registration form, which is persisted
-     * in the database. Default value is false.
-     * Accepted values: boolean true or false
-     */
-    'enable_display_name'     => true,
-    /**
-     * Authentication Adapters
-     * Specify the adapters that will be used to try and authenticate the user
-     * Default value: array containing 'ZfcUser\Authentication\Adapter\Db' with priority 100
-     * Accepted values: array containing services that implement 'ZfcUser\Authentication\Adapter\ChainableAdapter'
-     */
-    'auth_adapters'           => [
-        300 => 'UnicaenAuth\Authentication\Adapter\Ldap', // notifié en 1er
-        200 => 'UnicaenAuth\Authentication\Adapter\Db',   //         ensuite (si échec d'authentification Ldap)
-        100 => 'UnicaenAuth\Authentication\Adapter\Cas',  //         ensuite (si échec d'authentification Db)
+        100 => 'UnicaenAuth\Provider\Identity\Ldap',  // en 3e @deprecated
     ],
-
-    // telling ZfcUser to use our own class
-    'user_entity_class'       => 'UnicaenAuth\Entity\Db\User',
-    // telling ZfcUserDoctrineORM to skip the entities it defines
-    'enable_default_entities' => false,
 ];
 
-$bjyauthorize = [
-    /* this module uses a meta-role that inherits from any roles that should
-     * be applied to the active user. the identity provider tells us which
-     * roles the "identity role" should inherit from.
-     *
-     * for ZfcUser, this will be your default identity provider
-     */
-    'identity_provider'     => 'UnicaenAuth\Provider\Identity\Chain',
-
-    /* role providers simply provide a list of roles that should be inserted
-     * into the Zend\Acl instance. the module comes with two providers, one
-     * to specify roles in a config file and one to load roles using a
-     * Zend\Db adapter.
-     */
-    'role_providers'        => [
+return [
+    'zfcuser'         => [
         /**
-         * 2 rôles doivent systématiquement exister dans les ACL :
-         * - le rôle par défaut 'guest', c'est le rôle de tout utilisateur non authentifié.
-         * - le rôle 'user', c'est le rôle de tout utilisateur authentifié.
+         * Enable registration
+         * Allows users to register through the website.
+         * Accepted values: boolean true or false
          */
-        'UnicaenAuth\Provider\Role\Config'   => [
-            'guest' => ['name' => "Non authentifié(e)", 'selectable' => false, 'children' => [
-                'user' => ['name' => "Authentifié(e)", 'selectable' => false],
-            ]],
-        ],
+        'enable_registration'     => true,
         /**
-         * Fournit les rôles issus de la base de données éventuelle de l'appli.
-         * NB: si le rôle par défaut 'guest' est fourni ici, il ne sera pas ajouté en double dans les ACL.
-         * NB: si la connexion à la base échoue, ce n'est pas bloquant!
+         * Modes for authentication identity match
+         * Specify the allowable identity modes, in the order they should be
+         * checked by the Authentication plugin.
+         * Default value: array containing 'email'
+         * Accepted values: array containing one or more of: email, username
          */
-        'UnicaenAuth\Provider\Role\DbRole'   => [
-            'object_manager'    => 'doctrine.entitymanager.orm_default',
-            'role_entity_class' => 'UnicaenAuth\Entity\Db\Role',
-        ],
+        'auth_identity_fields'    => ['username', 'email'],
+        /**
+         * Login Redirect Route
+         * Upon successful login the user will be redirected to the entered route
+         * Default value: 'zfcuser'
+         * Accepted values: A valid route name within your application
+         */
+        'login_redirect_route'    => 'home',
         /**
-         * Fournit le rôle correspondant à l'identifiant de connexion de l'utilisateur.
-         * Cela est utile lorsque l'on veut gérer les habilitations d'un utilisateur unique
-         * sur des ressources.
+         * Logout Redirect Route
+         * Upon logging out the user will be redirected to the enterd route
+         * Default value: 'zfcuser/login'
+         * Accepted values: A valid route name within your application
          */
-        'UnicaenAuth\Provider\Role\Username' => [],
+        'logout_redirect_route'   => 'home',
+        /**
+         * Enable Username
+         * Enables username field on the registration form, and allows users to log
+         * in using their username OR email address. Default is false.
+         * Accepted values: boolean true or false
+         */
+        'enable_username'         => false,
+        /**
+         * Enable Display Name
+         * Enables a display name field on the registration form, which is persisted
+         * in the database. Default value is false.
+         * Accepted values: boolean true or false
+         */
+        'enable_display_name'     => true,
+        /**
+         * Authentication Adapters
+         * Specify the adapters that will be used to try and authenticate the user
+         * Default value: array containing 'ZfcUser\Authentication\Adapter\Db' with priority 100
+         * Accepted values: array containing services that implement 'ZfcUser\Authentication\Adapter\ChainableAdapter'
+         */
+        'auth_adapters'           => [
+            300 => 'UnicaenAuth\Authentication\Adapter\Ldap', // notifié en 1er
+            200 => 'UnicaenAuth\Authentication\Adapter\Db',   //         ensuite (si échec d'authentification Ldap)
+            100 => 'UnicaenAuth\Authentication\Adapter\Cas',  //         ensuite (si échec d'authentification Db)
+        ],
+
+        // telling ZfcUser to use our own class
+        'user_entity_class'       => 'UnicaenAuth\Entity\Db\User',
+        // telling ZfcUserDoctrineORM to skip the entities it defines
+        'enable_default_entities' => false,
     ],
+    'bjyauthorize'    => [
+        /* this module uses a meta-role that inherits from any roles that should
+         * be applied to the active user. the identity provider tells us which
+         * roles the "identity role" should inherit from.
+         *
+         * for ZfcUser, this will be your default identity provider
+         */
+        'identity_provider' => 'UnicaenAuth\Provider\Identity\Chain',
 
-    // strategy service name for the strategy listener to be used when permission-related errors are detected
-    //    'unauthorized_strategy' => 'BjyAuthorize\View\RedirectionStrategy',
-    'unauthorized_strategy' => 'UnicaenAuth\View\RedirectionStrategy',
+        /* role providers simply provide a list of roles that should be inserted
+         * into the Zend\Acl instance. the module comes with two providers, one
+         * to specify roles in a config file and one to load roles using a
+         * Zend\Db adapter.
+         */
+        'role_providers'    => [
+            /**
+             * 2 rôles doivent systématiquement exister dans les ACL :
+             * - le rôle par défaut 'guest', c'est le rôle de tout utilisateur non authentifié.
+             * - le rôle 'user', c'est le rôle de tout utilisateur authentifié.
+             */
+            'UnicaenAuth\Provider\Role\Config'   => [
+                'guest' => ['name' => "Non authentifié(e)", 'selectable' => false, 'children' => [
+                    'user' => ['name' => "Authentifié(e)", 'selectable' => false],
+                ]],
+            ],
+            /**
+             * Fournit les rôles issus de la base de données éventuelle de l'appli.
+             * NB: si le rôle par défaut 'guest' est fourni ici, il ne sera pas ajouté en double dans les ACL.
+             * NB: si la connexion à la base échoue, ce n'est pas bloquant!
+             */
+            'UnicaenAuth\Provider\Role\DbRole'   => [],
+            /**
+             * Fournit le rôle correspondant à l'identifiant de connexion de l'utilisateur.
+             * Cela est utile lorsque l'on veut gérer les habilitations d'un utilisateur unique
+             * sur des ressources.
+             */
+            'UnicaenAuth\Provider\Role\Username' => [],
+        ],
 
-    /* Currently, only controller and route guards exist
-     */
-    'guards'                => [
-        /* If this guard is specified here (i.e. it is enabled), it will block
-         * access to all controllers and actions unless they are specified here.
-         * You may omit the 'action' index to allow access to the entire controller
+        'rule_providers' => [
+            //'UnicaenAuth\Provider\Rule\PrivilegeRuleProvider' => [],
+        ],
+
+        'resource_providers'    => [
+            'UnicaenAuth\Service\Privilege' => [],
+        ],
+
+        // strategy service name for the strategy listener to be used when permission-related errors are detected
+        //    'unauthorized_strategy' => 'BjyAuthorize\View\RedirectionStrategy',
+        'unauthorized_strategy' => 'UnicaenAuth\View\RedirectionStrategy',
+
+        /* Currently, only controller and route guards exist
          */
-        'BjyAuthorize\Guard\Controller' => [
-            ['controller' => 'index', 'action' => 'index', 'roles' => []],
-            ['controller' => 'zfcuser', 'roles' => []],
-            ['controller' => 'Application\Controller\Index', 'roles' => []],
+        'guards'                => [
+            /* If this guard is specified here (i.e. it is enabled), it will block
+             * access to all controllers and actions unless they are specified here.
+             * You may omit the 'action' index to allow access to the entire controller
+             */
+            'BjyAuthorize\Guard\Controller'         => [
+                ['controller' => 'index', 'action' => 'index', 'roles' => []],
+                ['controller' => 'zfcuser', 'roles' => []],
+                ['controller' => 'Application\Controller\Index', 'roles' => []],
 
-            ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'etab', 'roles' => []],
-            ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'apropos', 'roles' => []],
-            ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'contact', 'roles' => []],
-            ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'plan', 'roles' => []],
-            ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'mentions-legales', 'roles' => []],
-            ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'informatique-et-libertes', 'roles' => []],
-            ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'refresh-session', 'roles' => []],
-            ['controller' => 'UnicaenAuth\Controller\Utilisateur', 'action' => 'selectionner-profil', 'roles' => []],
+                ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'etab', 'roles' => []],
+                ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'apropos', 'roles' => []],
+                ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'contact', 'roles' => []],
+                ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'plan', 'roles' => []],
+                ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'mentions-legales', 'roles' => []],
+                ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'informatique-et-libertes', 'roles' => []],
+                ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'refresh-session', 'roles' => []],
+                ['controller' => 'UnicaenAuth\Controller\Utilisateur', 'action' => 'selectionner-profil', 'roles' => []],
+            ],
+            'UnicaenAuth\Guard\PrivilegeController' => [
+                [
+                    'controller' => 'UnicaenAuth\Controller\Droits',
+                    'action'     => ['index'],
+                    'privileges' => [
+                        Privileges::DROIT_ROLE_VISUALISATION,
+                        Privileges::DROIT_PRIVILEGE_VISUALISATION,
+                    ],
+                ],
+                [
+                    'controller' => 'UnicaenAuth\Controller\Droits',
+                    'action'     => ['roles'],
+                    'privileges' => [Privileges::DROIT_ROLE_VISUALISATION],
+                ],
+                [
+                    'controller' => 'UnicaenAuth\Controller\Droits',
+                    'action'     => ['privileges'],
+                    'privileges' => [Privileges::DROIT_PRIVILEGE_VISUALISATION],
+                ],
+                [
+                    'controller' => 'UnicaenAuth\Controller\Droits',
+                    'action'     => ['role-edition', 'role-suppression'],
+                    'privileges' => [Privileges::DROIT_ROLE_EDITION],
+                ],
+                [
+                    'controller' => 'UnicaenAuth\Controller\Droits',
+                    'action'     => ['privileges-modifier'],
+                    'privileges' => [Privileges::DROIT_PRIVILEGE_EDITION],
+                ],
+            ],
         ],
     ],
-];
-
-return [
-    'zfcuser'         => $zfcuserSettings,
-    'bjyauthorize'    => $bjyauthorize,
     'unicaen-auth'    => $settings,
     'doctrine'        => [
         'driver' => [
@@ -170,41 +206,6 @@ return [
             ],
         ],
     ],
-    'service_manager' => [
-        'aliases'            => [
-            'Zend\Authentication\AuthenticationService' => 'zfcuser_auth_service',
-        ],
-        'invokables'         => [
-            'unicaen-auth_user_service'               => 'UnicaenAuth\Service\User',
-            'UnicaenAuth\Authentication\Storage\Db'   => 'UnicaenAuth\Authentication\Storage\Db',
-            'UnicaenAuth\Authentication\Storage\Ldap' => 'UnicaenAuth\Authentication\Storage\Ldap',
-            'UnicaenAuth\View\RedirectionStrategy'    => 'UnicaenAuth\View\RedirectionStrategy',
-            'authUserContext'                         => 'UnicaenAuth\Service\UserContext',
-        ],
-        'abstract_factories' => [
-            'UnicaenAuth\Authentication\Adapter\AbstractFactory',
-        ],
-        'factories'          => [
-            'unicaen-auth_module_options'              => 'UnicaenAuth\Options\ModuleOptionsFactory',
-            'zfcuser_auth_service'                     => 'UnicaenAuth\Authentication\AuthenticationServiceFactory',
-            'UnicaenAuth\Authentication\Storage\Chain' => 'UnicaenAuth\Authentication\Storage\ChainServiceFactory',
-            'UnicaenAuth\Provider\Identity\Chain'      => 'UnicaenAuth\Provider\Identity\ChainServiceFactory',
-            'UnicaenAuth\Provider\Identity\Ldap'       => 'UnicaenAuth\Provider\Identity\LdapServiceFactory',
-            'UnicaenAuth\Provider\Identity\Db'         => 'UnicaenAuth\Provider\Identity\DbServiceFactory',
-            'UnicaenAuth\Provider\Identity\Basic'      => 'UnicaenAuth\Provider\Identity\BasicServiceFactory',
-            'UnicaenAuth\Provider\Role\Config'         => 'UnicaenAuth\Provider\Role\ConfigServiceFactory',
-            'UnicaenAuth\Provider\Role\DbRole'         => 'UnicaenAuth\Provider\Role\DbRoleServiceFactory',
-            'UnicaenAuth\Provider\Role\Username'       => 'UnicaenAuth\Provider\Role\UsernameServiceFactory',
-        ],
-        'initializers'       => [
-            'UnicaenAuth\Service\UserAwareInitializer',
-        ],
-    ],
-    'controllers'     => [
-        'invokables' => [
-            'UnicaenAuth\Controller\Utilisateur' => 'UnicaenAuth\Controller\UtilisateurController',
-        ],
-    ],
     'view_manager'    => [
         'template_map'        => [
             'error/403' => __DIR__ . '/../view/error/403.phtml',
@@ -295,6 +296,80 @@ return [
                     ],
                 ],
             ],
+            'droits'      => [
+                'type'          => 'Literal',
+                'options'       => [
+                    'route'    => '/droits',
+                    'defaults' => [
+                        '__NAMESPACE__' => 'UnicaenAuth\Controller',
+                        'controller'    => 'Droits',
+                        'action'        => 'index',
+                    ],
+                ],
+                'may_terminate' => true,
+                'child_routes'  => [
+                    'roles'      => [
+                        'type'          => 'Segment',
+                        'may_terminate' => true,
+                        'options'       => [
+                            'route'    => '/roles',
+                            'defaults' => [
+                                'action' => 'roles',
+                            ],
+                        ],
+                        'child_routes'  => [
+                            'edition'     => [
+                                'type'          => 'Segment',
+                                'may_terminate' => true,
+                                'options'       => [
+                                    'route'       => '/edition[/:role]',
+                                    'constraints' => [
+                                        'role' => '[0-9]*',
+                                    ],
+                                    'defaults'    => [
+                                        'action' => 'role-edition',
+                                    ],
+                                ],
+                            ],
+                            'suppression' => [
+                                'type'          => 'Segment',
+                                'may_terminate' => true,
+                                'options'       => [
+                                    'route'       => '/suppression/:role',
+                                    'constraints' => [
+                                        'role' => '[0-9]*',
+                                    ],
+                                    'defaults'    => [
+                                        'action' => 'role-suppression',
+                                    ],
+                                ],
+                            ],
+                        ],
+                    ],
+                    'privileges' => [
+                        'type'          => 'Literal',
+                        'may_terminate' => true,
+                        'options'       => [
+                            'route'    => '/privileges',
+                            'defaults' => [
+                                'action' => 'privileges',
+                            ],
+                        ],
+                        'child_routes'  => [
+                            'modifier' => [
+                                'type'          => 'Segment',
+                                'may_terminate' => true,
+                                'options'       => [
+                                    'route'    => '/modifier',
+                                    'defaults' => [
+                                        'action' => 'privileges-modifier',
+                                    ],
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
         ],
     ],
     // All navigation-related configuration is collected in the 'navigation' key
@@ -318,8 +393,59 @@ return [
             ],
         ],
     ],
+    'service_manager' => [
+        'aliases'            => [
+            'Zend\Authentication\AuthenticationService' => 'zfcuser_auth_service',
+            'UnicaenAuth\Privilege\PrivilegeProvider'   => 'UnicaenAuth\Service\Privilege',
+
+            'unicaen-auth_user_service'               => 'UnicaenAuth\Service\User', // pour la compatibilité
+            'authUserContext'                         => 'UnicaenAuth\Service\UserContext', // pour la compatibilité
+        ],
+        'invokables'         => [
+            'UnicaenAuth\Authentication\Storage\Db'   => 'UnicaenAuth\Authentication\Storage\Db',
+            'UnicaenAuth\Authentication\Storage\Ldap' => 'UnicaenAuth\Authentication\Storage\Ldap',
+            'UnicaenAuth\View\RedirectionStrategy'    => 'UnicaenAuth\View\RedirectionStrategy',
+            'UnicaenAuth\Service\UserContext'         => 'UnicaenAuth\Service\UserContext',
+            'UnicaenAuth\Service\User'                => 'UnicaenAuth\Service\User',
+            'UnicaenAuth\Service\Privilege'           => 'UnicaenAuth\Service\PrivilegeService',
+            'UnicaenAuth\Service\CategoriePrivilege'  => 'UnicaenAuth\Service\CategoriePrivilegeService',
+            'UnicaenAuth\Service\Role'                => 'UnicaenAuth\Service\RoleService',
+        ],
+        'abstract_factories' => [
+            'UnicaenAuth\Authentication\Adapter\AbstractFactory',
+        ],
+        'factories'          => [
+            'unicaen-auth_module_options'              => 'UnicaenAuth\Options\ModuleOptionsFactory',
+            'zfcuser_auth_service'                     => 'UnicaenAuth\Authentication\AuthenticationServiceFactory',
+            'UnicaenAuth\Authentication\Storage\Chain' => 'UnicaenAuth\Authentication\Storage\ChainServiceFactory',
+            'UnicaenAuth\Provider\Identity\Chain'      => 'UnicaenAuth\Provider\Identity\ChainServiceFactory',
+            'UnicaenAuth\Provider\Identity\Ldap'       => 'UnicaenAuth\Provider\Identity\LdapServiceFactory',
+            'UnicaenAuth\Provider\Identity\Db'         => 'UnicaenAuth\Provider\Identity\DbServiceFactory',
+            'UnicaenAuth\Provider\Identity\Basic'      => 'UnicaenAuth\Provider\Identity\BasicServiceFactory',
+            'UnicaenAuth\Provider\Role\Config'         => 'UnicaenAuth\Provider\Role\ConfigServiceFactory',
+            'UnicaenAuth\Provider\Role\DbRole'         => 'UnicaenAuth\Provider\Role\DbRoleServiceFactory',
+            'UnicaenAuth\Provider\Role\Username'       => 'UnicaenAuth\Provider\Role\UsernameServiceFactory',
+            'BjyAuthorize\Service\Authorize'           => 'UnicaenAuth\Service\AuthorizeServiceFactory', // surcharge!!!
+        ],
+        'initializers'       => [
+            'UnicaenAuth\Service\UserAwareInitializer',
+        ],
+    ],
+
+    'controllers'   => [
+        'invokables' => [
+            'UnicaenAuth\Controller\Utilisateur' => 'UnicaenAuth\Controller\UtilisateurController',
+            'UnicaenAuth\Controller\Droits'      => 'UnicaenAuth\Controller\DroitsController',
+        ],
+    ],
+
+    'form_elements' => [
+        'invokables' => [
+            'UnicaenAuth\Form\Droits\Role' => 'UnicaenAuth\Form\Droits\RoleForm',
+        ],
+    ],
 
-    'view_helpers'    => [
+    'view_helpers'  => [
         'factories'  => [
             'userConnection'             => 'UnicaenAuth\View\Helper\UserConnectionFactory',
             'userCurrent'                => 'UnicaenAuth\View\Helper\UserCurrentFactory',
diff --git a/config/unicaen-auth.global.php.dist b/config/unicaen-auth.global.php.dist
index 4fe47f348323938983ab0b2431b40e4b090a1a7f..6be067c42a6d9e83e3c1357753ecc98b47b398a2 100644
--- a/config/unicaen-auth.global.php.dist
+++ b/config/unicaen-auth.global.php.dist
@@ -16,6 +16,11 @@ $settings = [
      * (i.e. créer un compte dans la table des utilisateurs).
      */
     'enable_registration' => false,
+    /**
+     * Nom du gestionnaire d'entités doctrine qui sera utilisé pour accéder à la base de données des rôles,
+     * utilisateurs et privilèges.
+     */
+    //'entity_manager_name' => 'doctrine.entitymanager.orm_default',
 ];
 
 /**
diff --git a/data/schema_mysql.sql b/data/schema_mysql.sql
index 35854ecae8e7c815f657050830be98fc52a9c56c..7d22ce0e15a9f7b24352ed65f230a561ce4826fc 100644
--- a/data/schema_mysql.sql
+++ b/data/schema_mysql.sql
@@ -9,6 +9,7 @@ CREATE TABLE user (
   UNIQUE INDEX `unique_username` (`username` ASC)
 ) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;
 
+
 CREATE TABLE IF NOT EXISTS `user_role` (
   `id` INT(11) NOT NULL AUTO_INCREMENT,
   `role_id` VARCHAR(64) NOT NULL,
@@ -21,6 +22,7 @@ CREATE TABLE IF NOT EXISTS `user_role` (
   CONSTRAINT `fk_parent_id` FOREIGN KEY (`parent_id`) REFERENCES `user_role` (`id`) ON DELETE SET NULL
 ) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;
 
+
 CREATE TABLE IF NOT EXISTS `user_role_linker` (
   `user_id` INT(11) NOT NULL,
   `role_id` INT(11) NOT NULL,
@@ -53,6 +55,7 @@ CREATE TABLE IF NOT EXISTS privilege (
   CONSTRAINT fk_categorie_id FOREIGN KEY (categorie_id) REFERENCES categorie_privilege (id) ON DELETE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;
 
+
 CREATE TABLE IF NOT EXISTS role_privilege (
   role_id       INT(11) NOT NULL,
   privilege_id  INT(11) NOT NULL,
@@ -63,8 +66,25 @@ CREATE TABLE IF NOT EXISTS role_privilege (
   CONSTRAINT fk_rp_privilege_id FOREIGN KEY (privilege_id) REFERENCES privilege (id) ON DELETE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;
 
+
+-- Données
 INSERT INTO `user_role` (`id`, `role_id`, `is_default`, `parent_id`) VALUES
 (1, 'Standard', 1, NULL),
 (2, 'Gestionnaire', 0, 1),
 (3, 'Super-gestionnaire', 0, 2),
-(4, 'Administrateur de l''application', 0, 3);
+(4, 'Administrateur', 0, 3);
+
+INSERT INTO `categorie_privilege` (`id`, `code`, `libelle`, `ordre`) VALUES
+(1, 'droit', 'Gestion des droits', 1);
+
+INSERT INTO `privilege` (`id`, `categorie_id`, `code`, `libelle`, `ordre`) VALUES
+(1, 1, 'role-visualisation', 'Rôles - Visualisation', 1),
+(2, 1, 'role-edition', 'Rôles - Édition', 2),
+(3, 1, 'privilege-visualisation', 'Privilèges - Visualisation', 3),
+(4, 1, 'privilege-edition', 'Privilèges - Édition', 4);
+
+INSERT INTO `role_privilege` (`role_id`, `privilege_id`) VALUES
+(4, 1),
+(4, 2),
+(4, 3),
+(4, 4);
\ No newline at end of file
diff --git a/data/schema_oracle.sql b/data/schema_oracle.sql
index 6fd8a31623d7940ea65080e09d491cad0280276e..e460e0a3619f4ac5618054a594d602e6e4b700f1 100644
--- a/data/schema_oracle.sql
+++ b/data/schema_oracle.sql
@@ -1,4 +1,4 @@
-CREATE TABLE "USER"
+CREATE TABLE USER
 (	"ID" NUMBER(*,0) NOT NULL ENABLE,
 	"USERNAME" VARCHAR2(255 CHAR),
 	"EMAIL" VARCHAR2(255 CHAR),
@@ -8,7 +8,7 @@ CREATE TABLE "USER"
 	CONSTRAINT "USER_USERNAME_UN" UNIQUE ("USERNAME")
 );
 
-CREATE TABLE "USER_ROLE"
+CREATE TABLE USER_ROLE
 (	"ID" NUMBER(*,0) NOT NULL ENABLE,
 	"ROLE_ID" VARCHAR2(64 CHAR) NOT NULL ENABLE,
 	"IS_DEFAULT" NUMBER(38,0) NOT NULL ENABLE,
@@ -19,7 +19,7 @@ CREATE TABLE "USER_ROLE"
 );
 CREATE INDEX "USER_ROLE_PARENT__IDX" ON "USER_ROLE" ("PARENT_ID");
 
-CREATE TABLE "OSE"."USER_ROLE_LINKER"
+CREATE TABLE USER_ROLE_LINKER
 (	"USER_ID" NUMBER(*,0) NOT NULL ENABLE,
 	"ROLE_ID" NUMBER(*,0) NOT NULL ENABLE,
 	CONSTRAINT "USER_ROLE_LINKER_PK" PRIMARY KEY ("USER_ID", "ROLE_ID")
@@ -27,4 +27,3 @@ CREATE TABLE "OSE"."USER_ROLE_LINKER"
 	CONSTRAINT "USER_ROLE_USER_ROLE_FK" FOREIGN KEY ("ROLE_ID") REFERENCES "USER_ROLE" ("ID") ON DELETE CASCADE ENABLE
 );
 CREATE INDEX "USER_ROLE_LINKER_ROLE_IDX" ON "USER_ROLE_LINKER" ("ROLE_ID");
-CREATE INDEX "USER_ROLE_LINKER_USER_IDX" ON "USER_ROLE_LINKER" ("USER_ID");
\ No newline at end of file
diff --git a/src/UnicaenAuth/Assertion/AbstractAssertion.php b/src/UnicaenAuth/Assertion/AbstractAssertion.php
new file mode 100644
index 0000000000000000000000000000000000000000..0a589b3fba6fa72de87796dca438c4c33e7340e3
--- /dev/null
+++ b/src/UnicaenAuth/Assertion/AbstractAssertion.php
@@ -0,0 +1,200 @@
+<?php
+
+namespace UnicaenAuth\Assertion;
+
+use Zend\Mvc\MvcEvent;
+use Zend\Permissions\Acl\Acl;
+use Zend\Permissions\Acl\Assertion\AssertionInterface;
+use Zend\Permissions\Acl\Resource\ResourceInterface;
+use Zend\Permissions\Acl\Role\RoleInterface;
+use Zend\ServiceManager\ServiceLocatorAwareInterface;
+use Zend\ServiceManager\ServiceLocatorAwareTrait;
+
+/**
+ * Description of AbstractAssertion
+ *
+ * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ */
+abstract class AbstractAssertion implements AssertionInterface, ServiceLocatorAwareInterface
+{
+    use ServiceLocatorAwareTrait;
+
+
+
+    /**
+     * !!!! Pour éviter l'erreur "Serialization of 'Closure' is not allowed"... !!!!
+     *
+     * @return array
+     */
+    public function __sleep()
+    {
+        return [];
+    }
+
+
+
+    /**
+     * Returns true if and only if the assertion conditions are met
+     *
+     * This method is passed the ACL, Role, Resource, and privilege to which the authorization query applies. If the
+     * $role, $this->resource, or $privilege parameters are null, it means that the query applies to all Roles, Resources, or
+     * privileges, respectively.
+     *
+     * @param  Acl               $acl
+     * @param  RoleInterface     $role
+     * @param  ResourceInterface $resource
+     * @param  string            $privilege
+     *
+     * @return bool
+     */
+    public final function assert(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null)
+    {
+        switch (true) {
+            case $this->detectPrivilege($resource):
+
+                return $this->assertPrivilege($acl, $role, ltrim(strstr($resource, '/'), '/'), $privilege);
+
+            case $this->detectController($resource):
+
+                $resource   = (string)$resource;
+                $spos       = strpos($resource, '/') + 1;
+                $dpos       = strrpos($resource, ':') + 1;
+                $controller = substr($resource, $spos, $dpos - $spos - 1);
+                $action     = substr($resource, $dpos);
+
+                return $this->assertController($acl, $role, $controller, $action, $privilege);
+
+            case $this->detectEntity($resource):
+
+                return $this->assertEntity($acl, $role, $resource, $privilege);
+
+            default:
+
+                return $this->assertOther($acl, $role, $resource, $privilege);
+        }
+    }
+
+
+
+    /**
+     *
+     * @param string $resource
+     *
+     * @return boolean
+     */
+    private function detectPrivilege($resource = null)
+    {
+        if ($resource instanceof ResourceInterface) $resource = $resource->getResourceId();
+
+        return is_string($resource) && 0 === strpos($resource, 'privilege/');
+    }
+
+
+
+    /**
+     *
+     * @param Acl           $acl
+     * @param RoleInterface $role
+     * @param string        $privilege
+     * @param string        $subPrivilege
+     *
+     * @return boolean
+     */
+    protected function assertPrivilege(Acl $acl, RoleInterface $role = null, $privilege = null, $subPrivilege = null)
+    {
+        return true;
+    }
+
+
+
+    /**
+     *
+     * @param string $resource
+     *
+     * @return boolean
+     */
+    private function detectController($resource = null)
+    {
+        if ($resource instanceof ResourceInterface) $resource = $resource->getResourceId();
+
+        return 0 === strpos($resource, 'controller/');
+    }
+
+
+
+    /**
+     *
+     * @param Acl           $acl
+     * @param RoleInterface $role
+     * @param string        $controller
+     * @param string        $action
+     * @param string        $privilege
+     *
+     * @return boolean
+     */
+    protected function assertController(Acl $acl, RoleInterface $role = null, $controller = null, $action = null, $privilege = null)
+    {
+        return true;
+    }
+
+
+
+    /**
+     *
+     * @param string $resource
+     *
+     * @return boolean
+     */
+    private function detectEntity($resource = null)
+    {
+        return
+            is_object($resource)
+            && method_exists($resource, 'getId');
+    }
+
+
+
+    /**
+     *
+     * @param Acl               $acl
+     * @param RoleInterface     $role
+     * @param ResourceInterface $entity
+     * @param string            $privilege
+     *
+     * @return boolean
+     */
+    protected function assertEntity(Acl $acl, RoleInterface $role = null, ResourceInterface $entity = null, $privilege = null)
+    {
+        return true;
+    }
+
+
+
+    /**
+     *
+     * @param Acl               $acl
+     * @param RoleInterface     $role
+     * @param ResourceInterface $entity
+     * @param string            $privilege
+     *
+     * @return boolean
+     */
+    protected function assertOther(Acl $acl, RoleInterface $role = null, ResourceInterface $entity = null, $privilege = null)
+    {
+        return true;
+    }
+
+
+
+    /**
+     *
+     * @return MvcEvent
+     */
+    protected function getMvcEvent()
+    {
+        $application = $this->getServiceLocator()->get('Application');
+
+        return $application->getMvcEvent();
+    }
+
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/Controller/DroitsController.php b/src/UnicaenAuth/Controller/DroitsController.php
new file mode 100644
index 0000000000000000000000000000000000000000..cb0343fce9b4854f0a9096ae1dea4cda1dd725ff
--- /dev/null
+++ b/src/UnicaenAuth/Controller/DroitsController.php
@@ -0,0 +1,173 @@
+<?php
+
+namespace UnicaenAuth\Controller;
+
+use UnicaenAuth\Entity\Db\Privilege;
+use UnicaenAuth\Entity\Db\Role;
+use UnicaenAuth\Form\Droits\Traits\RoleFormAwareTrait;
+use UnicaenAuth\Service\Traits\PrivilegeServiceAwareTrait;
+use UnicaenAuth\Service\Traits\RoleServiceAwareTrait;
+use Zend\Form\Form;
+use Zend\Mvc\Controller\AbstractActionController;
+use Zend\View\Model\ViewModel;
+
+
+/**
+ * Description of DroitsController
+ *
+ *
+ * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ */
+class DroitsController extends AbstractActionController
+{
+    use RoleServiceAwareTrait;
+    use RoleFormAwareTrait;
+    use PrivilegeServiceAwareTrait;
+
+
+
+    /**
+     *
+     * @return type
+     */
+    public function indexAction()
+    {
+        return [];
+    }
+
+
+
+    public function rolesAction()
+    {
+        $roles = $this->getServiceRole()->getList();
+
+        return compact('roles');
+    }
+
+
+
+    public function roleEditionAction()
+    {
+        $roleId = $this->params()->fromRoute('role');
+        $role   = $this->getServiceRole()->get($roleId);
+        $errors = [];
+
+        $form = $this->getFormDroitsRole();
+        if (empty($role)) {
+            $title = 'Création d\'un nouveau rôle';
+            $role  = $this->getServiceRole()->newEntity();
+            $form->setObject($role);
+        } else {
+            $title = 'Édition du rôle';
+            $form->bind($role);
+        }
+        $form->setAttribute('action', $this->url()->fromRoute(null, [], [], true));
+
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $form->setData($request->getPost());
+            if ($form->isValid()) {
+                try {
+                    $this->getServiceRole()->save($role);
+                    $form->get('id')->setValue($role->getId()); // transmet le nouvel ID
+                } catch (\Exception $e) {
+                    $errors[] = $e->getMessage();
+                }
+            }
+        }
+
+        return compact('form', 'title', 'errors');
+    }
+
+
+
+    public function roleSuppressionAction()
+    {
+        $roleId = $this->params()->fromRoute('role');
+        $role   = $this->getServiceRole()->get($roleId);
+
+        $title  = "Suppression du rôle";
+        $form   = $this->getFormSupprimer();
+        $errors = [];
+
+        if ($this->getRequest()->isPost()) {
+            try {
+                $this->getServiceRole()->delete($role);
+            } catch (\Exception $e) {
+                $errors[] = $e->getMessage();
+            }
+        }
+
+        return compact('role', 'title', 'form', 'errors');
+    }
+
+
+
+    public function privilegesAction()
+    {
+        $ps         = $this->getServicePrivilege()->getList();
+        $privileges = [];
+        foreach ($ps as $privilege) {
+            $categorie = $privilege->getCategorie();
+            if (!isset($privileges[$categorie->getCode()])) {
+                $privileges[$categorie->getCode()] = [
+                    'categorie'  => $categorie,
+                    'privileges' => [],
+                ];
+            }
+            $privileges[$categorie->getCode()]['privileges'][] = $privilege;
+        }
+
+        $roles = $this->getServiceRole()->getList();
+
+        return compact('privileges', 'roles');
+    }
+
+
+
+    public function privilegesModifierAction()
+    {
+        $roleId = $this->params()->fromPost('role');
+        $role   = $this->getServiceRole()->get($roleId);
+
+        $privilegeId = $this->params()->fromPost('privilege');
+        $privilege   = $this->getServicePrivilege()->get($privilegeId);
+
+        $action    = $this->params()->fromPost('action');
+
+        switch ($action) {
+            case 'accorder':
+                $this->getServicePrivilege()->addRole($privilege,$role);
+                break;
+            case 'refuser':
+                $this->getServicePrivilege()->removeRole($privilege,$role);
+                break;
+        }
+
+        $viewModel = new ViewModel();
+        $viewModel->setVariables(compact('role', 'privilege'))
+            ->setTerminal(true);
+
+        return $viewModel;
+    }
+
+
+
+    public function getFormSupprimer()
+    {
+        $form = new Form();
+        $form->add([
+            'name' => 'id',
+            'type' => 'Hidden',
+        ]);
+        $form->add([
+            'name' => 'submit',
+            'type'  => 'Submit',
+            'attributes' => [
+                'value' => 'Je confirme la suppression',
+            ],
+        ]);
+        $form->setAttribute('action', $this->url()->fromRoute(null, [], [], true));
+        return $form;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/Entity/Db/CategoriePrivilege.php b/src/UnicaenAuth/Entity/Db/CategoriePrivilege.php
new file mode 100644
index 0000000000000000000000000000000000000000..4bc7a34d3cbbbd7f2f0bcc2f7786d42e88a95765
--- /dev/null
+++ b/src/UnicaenAuth/Entity/Db/CategoriePrivilege.php
@@ -0,0 +1,199 @@
+<?php
+
+namespace UnicaenAuth\Entity\Db;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ *
+ * @ORM\Entity
+ * @ORM\Table(name="categorie_privilege")
+ */
+class CategoriePrivilege
+{
+    /**
+     * @var int
+     * @ORM\Id
+     * @ORM\Column(type="integer")
+     * @ORM\GeneratedValue(strategy="AUTO")
+     */
+    private $id;
+
+    /**
+     * @var string
+     * @ORM\Column(name="code", type="string", length=150, unique=false, nullable=false)
+     */
+    private $code;
+
+    /**
+     * @var string
+     * @ORM\Column(name="libelle", type="string", length=200, unique=false, nullable=false)
+     */
+    private $libelle;
+
+    /**
+     * @var int
+     * @ORM\Column(name="ordre", type="integer", unique=false, nullable=false)
+     */
+    private $ordre;
+
+    /**
+     * @var \Doctrine\Common\Collections\Collection
+     * @ORM\OneToMany(targetEntity="Privilege", mappedBy="categorie")
+     */
+    private $privilege;
+
+
+
+    /**
+     * Constructor
+     */
+    public function __construct()
+    {
+        $this->privilege = new \Doctrine\Common\Collections\ArrayCollection();
+    }
+
+
+
+    /**
+     * Set code
+     *
+     * @param string $code
+     *
+     * @return Privilege
+     */
+    public function setCode($code)
+    {
+        $this->code = $code;
+
+        return $this;
+    }
+
+
+
+    /**
+     * Get code
+     *
+     * @return string
+     */
+    public function getCode()
+    {
+        return $this->code;
+    }
+
+
+
+    /**
+     * Set libelle
+     *
+     * @param string $libelle
+     *
+     * @return Privilege
+     */
+    public function setLibelle($libelle)
+    {
+        $this->libelle = $libelle;
+
+        return $this;
+    }
+
+
+
+    /**
+     * Get libelle
+     *
+     * @return string
+     */
+    public function getLibelle()
+    {
+        return $this->libelle;
+    }
+
+
+
+    /**
+     *
+     * @return integer
+     */
+    function getOrdre()
+    {
+        return $this->ordre;
+    }
+
+
+
+    /**
+     *
+     * @param integer $ordre
+     *
+     * @return \Application\Entity\Db\Privilege
+     */
+    function setOrdre($ordre)
+    {
+        $this->ordre = $ordre;
+
+        return $this;
+    }
+
+
+
+    /**
+     * Get id
+     *
+     * @return integer
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+
+
+
+    /**
+     * Add privilege
+     *
+     * @param Privilege $privilege
+     *
+     * @return Privilege
+     */
+    public function addPrivilege(Privilege $privilege)
+    {
+        $this->privilege[] = $privilege;
+
+        return $this;
+    }
+
+
+
+    /**
+     * Remove privilege
+     *
+     * @param Privilege $privilege
+     */
+    public function removePrivilege(Privilege $privilege)
+    {
+        $this->privilege->removeElement($privilege);
+    }
+
+
+
+    /**
+     * Get privilege
+     *
+     * @return \Doctrine\Common\Collections\Collection
+     */
+    public function getPrivilege()
+    {
+        return $this->privilege;
+    }
+
+
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        return $this->getLibelle();
+    }
+}
diff --git a/src/UnicaenAuth/Entity/Db/AbstractPrivilege.php b/src/UnicaenAuth/Entity/Db/Privilege.php
similarity index 62%
rename from src/UnicaenAuth/Entity/Db/AbstractPrivilege.php
rename to src/UnicaenAuth/Entity/Db/Privilege.php
index 54fab6bba88a2744cd63cb5f469edfaa6806fb68..45f4dcddb708aaa439a6541edbea2d903659f47d 100644
--- a/src/UnicaenAuth/Entity/Db/AbstractPrivilege.php
+++ b/src/UnicaenAuth/Entity/Db/Privilege.php
@@ -1,41 +1,59 @@
 <?php
 
 namespace UnicaenAuth\Entity\Db;
+
+use UnicaenAuth\Provider\Privilege\Privileges;
 use Zend\Permissions\Acl\Resource\ResourceInterface;
+use Doctrine\ORM\Mapping as ORM;
 
 /**
- * Privilege
+ *
+ * @ORM\Entity
+ * @ORM\Table(name="privilege")
  */
-abstract class AbstractPrivilege implements ResourceInterface
+class Privilege implements ResourceInterface
 {
+    /**
+     * @var int
+     * @ORM\Id
+     * @ORM\Column(type="integer")
+     * @ORM\GeneratedValue(strategy="AUTO")
+     */
+    private $id;
+
     /**
      * @var string
+     * @ORM\Column(name="code", type="string", length=150, unique=false, nullable=false)
      */
     private $code;
 
     /**
      * @var string
+     * @ORM\Column(name="libelle", type="string", length=200, unique=false, nullable=false)
      */
     private $libelle;
 
     /**
-     *
-     * @var integer
+     * @var int
+     * @ORM\Column(name="ordre", type="integer", unique=false, nullable=false)
      */
     private $ordre;
 
     /**
-     * @var integer
-     */
-    private $id;
-
-    /**
-     * @var \UnicaenApp\Entity\Db\CategoriePrivilege
+     * @var CategoriePrivilege
+     * @ORM\ManyToOne(targetEntity="CategoriePrivilege", inversedBy="privilege")
+     * @ORM\JoinColumn(name="categorie_id", referencedColumnName="id")
      */
     private $categorie;
 
     /**
-     * @var \Doctrine\Common\Collections\Collection
+     * @ORM\ManyToMany(targetEntity="UnicaenAuth\Entity\Db\Role",cascade={"all"})
+     * @ORM\JoinTable(
+     *     name="role_privilege",
+     *     joinColumns={@ORM\JoinColumn(name="privilege_id", referencedColumnName="id", onDelete="cascade")},
+     *     inverseJoinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id", onDelete="cascade")}
+     *
+     * )
      */
     private $role;
 
@@ -129,7 +147,7 @@ abstract class AbstractPrivilege implements ResourceInterface
      *
      * @param integer $ordre
      *
-     * @return \Application\Entity\Db\Privilege
+     * @return self
      */
     function setOrdre($ordre)
     {
@@ -155,11 +173,11 @@ abstract class AbstractPrivilege implements ResourceInterface
     /**
      * Set categorie
      *
-     * @param \Application\Entity\Db\CategoriePrivilege $categorie
+     * @param CategoriePrivilege $categorie
      *
-     * @return Privilege
+     * @return self
      */
-    public function setCategorie(\Application\Entity\Db\CategoriePrivilege $categorie = null)
+    public function setCategorie(CategoriePrivilege $categorie = null)
     {
         $this->categorie = $categorie;
 
@@ -171,7 +189,7 @@ abstract class AbstractPrivilege implements ResourceInterface
     /**
      * Get categorie
      *
-     * @return \Application\Entity\Db\CategoriePrivilege
+     * @return CategoriePrivilege
      */
     public function getCategorie()
     {
@@ -183,13 +201,13 @@ abstract class AbstractPrivilege implements ResourceInterface
     /**
      * Add role
      *
-     * @param \Application\Entity\Db\Role $role
+     * @param Role $role
      *
-     * @return Privilege
+     * @return self
      */
-    public function addRole(\Application\Entity\Db\Role $role)
+    public function addRole(Role $role)
     {
-        $this->Role[] = $role;
+        $this->role->add($role);
 
         return $this;
     }
@@ -199,9 +217,9 @@ abstract class AbstractPrivilege implements ResourceInterface
     /**
      * Remove role
      *
-     * @param \Application\Entity\Db\Role $role
+     * @param Role $role
      */
-    public function removeRole(\Application\Entity\Db\Role $role)
+    public function removeRole(Role $role)
     {
         $this->role->removeElement($role);
     }
@@ -220,23 +238,6 @@ abstract class AbstractPrivilege implements ResourceInterface
 
 
 
-    /**
-     * @deprecated
-     * @todo à voir si cela sert à quelque chose ou non !!
-     * @return array
-     */
-    public function getRoleCodes()
-    {
-        $result = [];
-        foreach ($this->role as $role) {
-            /* @var $role Role */
-            $result[] = $role->getRoleId();
-        }
-        return $result;
-    }
-
-
-
     /**
      * @return string
      */
@@ -252,6 +253,6 @@ abstract class AbstractPrivilege implements ResourceInterface
      */
     public function getResourceId()
     {
-        return sprintf('privilege/%s', $this->getFullCode());
+        return Privileges::getResource($this);
     }
 }
diff --git a/src/UnicaenAuth/Entity/Db/Role.php b/src/UnicaenAuth/Entity/Db/Role.php
index 472740fac9e9abf6299621ed31f0a5745b5880fe..dc358a5eafe2339c42d11871d558fa6af29d7fdc 100644
--- a/src/UnicaenAuth/Entity/Db/Role.php
+++ b/src/UnicaenAuth/Entity/Db/Role.php
@@ -35,9 +35,9 @@ class Role implements HierarchicalRoleInterface
 
     /**
      * @var boolean
-     * @ORM\Column(name="is_default", type="boolean", nullable=false)
+     * @ORM\Column(name="is_default", type="boolean", nullable=true)
      */
-    protected $isDefault;
+    protected $isDefault = false;
 
     /**
      * @var Role
diff --git a/src/UnicaenAuth/Form/Droits/RoleForm.php b/src/UnicaenAuth/Form/Droits/RoleForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..e2f5de973ff2e281eb28ee99140aff4921a16d6f
--- /dev/null
+++ b/src/UnicaenAuth/Form/Droits/RoleForm.php
@@ -0,0 +1,141 @@
+<?php
+
+namespace UnicaenAuth\Form\Droits;
+
+use UnicaenAuth\Entity\Db\Role;
+use UnicaenAuth\Service\Traits\RoleServiceAwareTrait;
+use Zend\Form\Form;
+use UnicaenApp\Util;
+use Zend\ServiceManager\ServiceLocatorAwareInterface;
+use Zend\ServiceManager\ServiceLocatorAwareTrait;
+use Zend\Stdlib\Hydrator\HydratorInterface;
+
+/**
+ * Description of RoleForm
+ *
+ * @author Laurent LECLUSE <laurent.lecluse at unicaen.fr>
+ */
+class RoleForm extends Form implements ServiceLocatorAwareInterface
+{
+    use ServiceLocatorAwareTrait;
+    use RoleServiceAwareTrait;
+
+    public function init()
+    {
+        $hydrator = new RoleFormHydrator;
+        $hydrator->setServiceRole( $this->getServiceRole() );
+        $this->setHydrator($hydrator);
+
+        $this->add([
+            'type'    => 'Text',
+            'name'    => 'role-id',
+            'options' => [
+                'label' => 'Nom',
+            ],
+        ]);
+
+        $this->add([
+            'type'    => 'Text',
+            'name'    => 'ldap-filter',
+            'options' => [
+                'label' => 'Filtre LDAP',
+            ],
+        ]);
+
+        $this->add([
+            'type' => 'Select',
+            'name' => 'parent',
+            'options' => [
+                'label' => 'Parent',
+                'empty_option' => '- Aucun -',
+                'value_options' => Util::collectionAsOptions($this->getServiceRole()->getList()),
+            ],
+        ]);
+
+        $this->add([
+            'name' => 'id',
+            'type' => 'Hidden',
+        ]);
+
+        $this->add([
+            'name'       => 'submit',
+            'type'       => 'Submit',
+            'attributes' => [
+                'value' => 'Enregistrer',
+                'class' => 'btn btn-primary',
+            ],
+        ]);
+    }
+
+
+
+    /**
+     * Should return an array specification compatible with
+     * {@link Zend\InputFilter\Factory::createInputFilter()}.
+     *
+     * @return array
+     */
+    public function getInputFilterSpecification()
+    {
+        return [
+            'role-id' => [
+                'required' => true,
+            ],
+            'ldap-filter' => [
+                'required' => false,
+            ],
+            'parent' => [
+                'required' => false,
+            ],
+        ];
+    }
+}
+
+
+
+
+
+/**
+ * Class RoleFormHydrator
+ *
+ * @package UnicaenAuth\Form\Droits
+ * @author  Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ */
+class RoleFormHydrator implements HydratorInterface
+{
+    use RoleServiceAwareTrait;
+
+    /**
+     * @param  array $data
+     * @param  Role  $object
+     *
+     * @return object
+     */
+    public function hydrate(array $data, $object)
+    {
+        $object->setRoleId($data['role-id']);
+        $object->setLdapFilter($data['ldap-filter'] ?: null);
+        $object->setParent($this->getServiceRole()->get($data['parent']));
+
+        return $object;
+    }
+
+
+
+    /**
+     * @param  Role $object
+     *
+     * @return array
+     */
+    public function extract($object)
+    {
+        $data = [
+            'id'          => $object->getId(),
+            'role-id'     => $object->getRoleId(),
+            'ldap-filter' => $object->getLdapFilter(),
+            'parent'      => $object->getParent() ? $object->getParent()->getId() : null,
+        ];
+
+        return $data;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/Form/Droits/Traits/RoleFormAwareTrait.php b/src/UnicaenAuth/Form/Droits/Traits/RoleFormAwareTrait.php
new file mode 100755
index 0000000000000000000000000000000000000000..02badad1729fccad2d0496df10986806196fd704
--- /dev/null
+++ b/src/UnicaenAuth/Form/Droits/Traits/RoleFormAwareTrait.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace UnicaenAuth\Form\Droits\Traits;
+
+use UnicaenAuth\Form\Droits\RoleForm;
+use RuntimeException;
+
+/**
+ * Description of RoleFormAwareTrait
+ *
+ * @author UnicaenCode
+ */
+trait RoleFormAwareTrait
+{
+    /**
+     * @var RoleForm
+     */
+    private $formDroitsRole;
+
+
+
+    /**
+     * @param RoleForm $formDroitsRole
+     *
+     * @return self
+     */
+    public function setFormDroitsRole(RoleForm $formDroitsRole)
+    {
+        $this->formDroitsRole = $formDroitsRole;
+
+        return $this;
+    }
+
+
+
+    /**
+     * @return RoleForm
+     * @throws RuntimeException
+     */
+    public function getFormDroitsRole()
+    {
+        if (empty($this->formDroitsRole)) {
+
+            if (!method_exists($this, 'getServiceLocator')) {
+                throw new RuntimeException('La classe ' . get_class($this) . ' n\'a pas accès au ServiceLocator.');
+            }
+
+            $serviceLocator = $this->getServiceLocator();
+            if (method_exists($serviceLocator, 'getServiceLocator')) {
+                $serviceLocator = $serviceLocator->getServiceLocator();
+            }
+
+            $this->formDroitsRole = $serviceLocator->get('FormElementManager')->get('UnicaenAuth\Form\Droits\Role');
+        }
+
+        return $this->formDroitsRole;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/Guard/PrivilegeController.php b/src/UnicaenAuth/Guard/PrivilegeController.php
new file mode 100644
index 0000000000000000000000000000000000000000..99b4f2d5158d71343f774be4730b6faba5500331
--- /dev/null
+++ b/src/UnicaenAuth/Guard/PrivilegeController.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace UnicaenAuth\Guard;
+
+use BjyAuthorize\Guard\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
+use UnicaenAuth\Provider\Privilege\PrivilegeProviderAwareTrait;
+use UnicaenApp\Traits\SessionContainerTrait;
+
+
+/**
+ * Description of ControllerGuard
+ *
+ * @author Laurent LECLUSE <laurent.lecluse at unicaen.fr>
+ */
+class PrivilegeController extends Controller
+{
+    use PrivilegeProviderAwareTrait;
+    use SessionContainerTrait;
+
+
+
+    public function __construct(array $rules, ServiceLocatorInterface $serviceLocator)
+    {
+        $this->serviceLocator = $serviceLocator;
+        parent::__construct($this->privilegesToRoles($rules), $serviceLocator);
+    }
+
+
+
+    protected function privilegesToRoles(array $rules)
+    {
+//        $session = $this->getSessionContainer();
+//        if (! isset($session->rules)){
+
+        $pr = $this->getPrivilegeProvider()->getPrivilegesRoles();
+
+        foreach ($rules as $index => $rule) {
+            if (isset($rule['privileges'])) {
+                $rolesCount    = 0;
+                $privileges    = (array)$rule['privileges'];
+                $rule['roles'] = isset($rule['roles']) ? (array)$rule['roles'] : [];
+                foreach ($pr as $privilege => $roles) {
+                    if (in_array($privilege, $privileges)) {
+                        $rolesCount += count($roles);
+                        $rule['roles'] = array_unique(array_merge($rule['roles'], $roles));
+                    }
+                }
+                unset($rule['privileges']);
+                if (0 < count($rule['roles'])) {
+                    $rules[$index] = $rule;
+                }else{
+                    unset($rules[$index]);
+                }
+            }
+        }
+
+        return $rules;
+//            $session->rules = $rules;
+//        }
+//        return $session->rules;
+    }
+
+
+
+    /**
+     * Pour récupérer le serviceLocator depuis les traits de service
+     *
+     * @return ServiceLocatorInterface
+     */
+    protected function getServiceLocator()
+    {
+        return $this->serviceLocator;
+    }
+
+
+
+    public static function getResourceId($controller, $action = null)
+    {
+        if (isset($action)) {
+            return sprintf('controller/%s:%s', $controller, strtolower($action));
+        }
+
+        return sprintf('controller/%s', $controller);
+    }
+
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/Options/ModuleOptions.php b/src/UnicaenAuth/Options/ModuleOptions.php
index 4f806e5249852123707e321c723e9564fd493ece..c5f942aa1972f0a539647a42adcfdda7fac5d7d3 100644
--- a/src/UnicaenAuth/Options/ModuleOptions.php
+++ b/src/UnicaenAuth/Options/ModuleOptions.php
@@ -23,18 +23,29 @@ class ModuleOptions extends \ZfcUser\Options\ModuleOptions
      */
     protected $cas = [];
 
+    /**
+     * @var string
+     */
+    protected $entityManagerName = 'doctrine.entitymanager.orm_default';
+
+
+
     /**
      * set usernames allowed to make usurpation
      *
      * @param array $usurpationAllowedUsernames
+     *
      * @return ModuleOptions
      */
     public function setUsurpationAllowedUsernames(array $usurpationAllowedUsernames = [])
     {
         $this->usurpationAllowedUsernames = $usurpationAllowedUsernames;
+
         return $this;
     }
 
+
+
     /**
      * get usernames allowed to make usurpation
      *
@@ -45,19 +56,25 @@ class ModuleOptions extends \ZfcUser\Options\ModuleOptions
         return $this->usurpationAllowedUsernames;
     }
 
+
+
     /**
      * Spécifie si l'utilisateur authentifié doit être enregistré dans la base
      * de données de l'appli
      *
      * @param bool $flag
+     *
      * @return ModuleOptions
      */
     public function setSaveLdapUserInDatabase($flag = true)
     {
-        $this->saveLdapUserInDatabase = (bool) $flag;
+        $this->saveLdapUserInDatabase = (bool)$flag;
+
         return $this;
     }
 
+
+
     /**
      * Retourne la valeur du flag spécifiant si l'utilisateur authentifié doit être
      * enregistré dans la base de données de l'appli
@@ -69,18 +86,24 @@ class ModuleOptions extends \ZfcUser\Options\ModuleOptions
         return $this->saveLdapUserInDatabase;
     }
 
+
+
     /**
      * set cas connection params
      *
      * @param array $cas
+     *
      * @return ModuleOptions
      */
     public function setCas(array $cas = [])
     {
         $this->cas = $cas;
+
         return $this;
     }
 
+
+
     /**
      * get cas connection params
      *
@@ -90,4 +113,30 @@ class ModuleOptions extends \ZfcUser\Options\ModuleOptions
     {
         return $this->cas;
     }
+
+
+
+    /**
+     * @return string
+     */
+    public function getEntityManagerName()
+    {
+        return $this->entityManagerName;
+    }
+
+
+
+    /**
+     * @param string $entityManagerName
+     *
+     * @return ModuleOptions
+     */
+    public function setEntityManagerName($entityManagerName)
+    {
+        $this->entityManagerName = $entityManagerName;
+
+        return $this;
+    }
+
+
 }
\ No newline at end of file
diff --git a/src/UnicaenAuth/Options/Traits/ModuleOptionsAwareTrait.php b/src/UnicaenAuth/Options/Traits/ModuleOptionsAwareTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..7d54cc5877fb515005194fd08ea2018da344e446
--- /dev/null
+++ b/src/UnicaenAuth/Options/Traits/ModuleOptionsAwareTrait.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace UnicaenAuth\Options\Traits;
+
+use UnicaenAuth\Options\ModuleOptions;
+use RuntimeException;
+
+/**
+ * Description of ModuleOptionsAwareTrait
+ *
+ * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ */
+trait ModuleOptionsAwareTrait
+{
+    /**
+     * @var ModuleOptions
+     */
+    private $moduleOptions;
+
+
+
+    /**
+     * @param ModuleOptions $moduleOptions
+     *
+     * @return self
+     */
+    public function setModuleOptions(ModuleOptions $moduleOptions)
+    {
+        $this->moduleOptions = $moduleOptions;
+
+        return $this;
+    }
+
+
+
+    /**
+     * @return ModuleOptions
+     * @throws RuntimeException
+     */
+    public function getModuleOptions()
+    {
+        if (empty($this->moduleOptions)) {
+            if (!method_exists($this, 'getServiceLocator')) {
+                throw new RuntimeException('La classe ' . get_class($this) . ' n\'a pas accès au ServiceLocator.');
+            }
+
+            $serviceLocator = $this->getServiceLocator();
+            if (method_exists($serviceLocator, 'getServiceLocator')) {
+                $serviceLocator = $serviceLocator->getServiceLocator();
+            }
+            $this->moduleOptions = $serviceLocator->get('unicaen-auth_module_options');
+        }
+
+        return $this->moduleOptions;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/Provider/Identity/Chain.php b/src/UnicaenAuth/Provider/Identity/Chain.php
index 59308d5bcee0a80bae5b5c1000e65f05d656de4c..67c2c61565ebe0a8597027c707b3ef09264a94f8 100644
--- a/src/UnicaenAuth/Provider/Identity/Chain.php
+++ b/src/UnicaenAuth/Provider/Identity/Chain.php
@@ -41,8 +41,8 @@ class Chain implements ProviderInterface, ServiceLocatorAwareInterface, EventMan
      */
     public function getIdentityRoles()
     {
-        $selectedIdentityRole = $this->getSelectedIdentityRole();
         $allRoles             = $this->getAllIdentityRoles();
+        $selectedIdentityRole = $this->getSelectedIdentityRole();
         $roles                = $selectedIdentityRole ? [$selectedIdentityRole] : $allRoles;
 
         return $roles;
diff --git a/src/UnicaenAuth/Provider/Identity/Db.php b/src/UnicaenAuth/Provider/Identity/Db.php
index f0d7ebb5e337304495f8c12fcc2c9ca3ae2e66e8..baa3f1453eb21b3538bc4169011a0e09bf91de18 100644
--- a/src/UnicaenAuth/Provider/Identity/Db.php
+++ b/src/UnicaenAuth/Provider/Identity/Db.php
@@ -3,6 +3,11 @@ namespace UnicaenAuth\Provider\Identity;
 
 use BjyAuthorize\Provider\Identity\AuthenticationIdentityProvider;
 use BjyAuthorize\Provider\Role\ProviderInterface;
+use UnicaenApp\Entity\Ldap\People;
+use UnicaenAuth\Entity\Db\Role;
+use UnicaenAuth\Service\Traits\RoleServiceAwareTrait;
+use Zend\Ldap\Ldap;
+use Zend\ServiceManager\ServiceLocatorAwareTrait;
 use ZfcUser\Entity\UserInterface;
 use Traversable;
 
@@ -16,8 +21,17 @@ use Traversable;
  *
  * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
  */
-class Db extends AuthenticationIdentityProvider implements ChainableProvider
+class Db extends AuthenticationIdentityProvider implements ChainableProvider, \BjyAuthorize\Provider\Identity\ProviderInterface
 {
+    use RoleServiceAwareTrait;
+
+    /**
+     * @var Ldap
+     */
+    private $ldap;
+
+
+
     /**
      * {@inheritDoc}
      */
@@ -26,17 +40,26 @@ class Db extends AuthenticationIdentityProvider implements ChainableProvider
         $event->addRoles($this->getIdentityRoles());
     }
 
+
+
     /**
      * {@inheritDoc}
      */
     public function getIdentityRoles()
     {
-        if (!($identity = $this->authService->getIdentity())) {
+        if (!($idArray = $this->authService->getIdentity())) {
             return [$this->defaultRole];
         }
 
-        if (is_array($identity) && isset($identity['db'])) {
-            $identity = $identity['db'];
+        $ldapDn   = null;
+        $identity = null;
+        if (is_array($idArray)) {
+            if (isset($idArray['ldap']) && $idArray['ldap'] instanceof People) {
+                $ldapDn = $idArray['ldap']->getDn();
+            }
+            if (isset($idArray['db'])) {
+                $identity = $idArray['db'];
+            }
         }
 
         if ($identity instanceof ProviderInterface) {
@@ -44,8 +67,7 @@ class Db extends AuthenticationIdentityProvider implements ChainableProvider
             if ($roles instanceof Traversable) {
                 $roles = iterator_to_array($roles);
             }
-        }
-        else {
+        } else {
             $roles = [];
         }
 
@@ -53,6 +75,61 @@ class Db extends AuthenticationIdentityProvider implements ChainableProvider
             $roles[] = $identity->getUsername();
         }
 
+        /* Injection des rôles par filtre LDAP */
+        $ldapRoles = $this->getServiceRole()->getList();
+        foreach ($ldapRoles as $role) {
+            if ($role->getLdapFilter() && !in_array($role, $roles)) {
+                if ($this->roleMatches($role, $ldapDn)) {
+                    $roles[] = $role;
+                }
+            }
+        }
+
         return $roles;
     }
+
+
+
+    /**
+     * @param Role   $role
+     * @param string $dn
+     *
+     * @return bool
+     */
+    protected function roleMatches(Role $role, $dn)
+    {
+        try {
+            return 1 === $this->getLdap()->count($role->getLdapFilter(), $dn, Ldap::SEARCH_SCOPE_SUB);
+        } catch (\Zend\Ldap\Exception\LdapException $e) {
+            return false;
+        }
+    }
+
+
+
+    /**
+     * Returns the LDAP Object
+     *
+     * @return Ldap
+     */
+    public function getLdap()
+    {
+        return $this->ldap;
+    }
+
+
+
+    /**
+     * Set an Ldap connection
+     *
+     * @param  Ldap $ldap
+     *
+     * @return self
+     */
+    public function setLdap(Ldap $ldap)
+    {
+        $this->ldap = $ldap;
+
+        return $this;
+    }
 }
\ No newline at end of file
diff --git a/src/UnicaenAuth/Provider/Identity/DbServiceFactory.php b/src/UnicaenAuth/Provider/Identity/DbServiceFactory.php
index afd4eb349c62402a65569d15e400a1cceabb20bb..a326639d8d78e3ce161381f813744f627d87760a 100644
--- a/src/UnicaenAuth/Provider/Identity/DbServiceFactory.php
+++ b/src/UnicaenAuth/Provider/Identity/DbServiceFactory.php
@@ -2,6 +2,8 @@
 
 namespace UnicaenAuth\Provider\Identity;
 
+use UnicaenApp\Options\ModuleOptions;
+use Zend\Ldap\Ldap;
 use Zend\ServiceManager\FactoryInterface;
 use Zend\ServiceManager\ServiceLocatorInterface;
 
@@ -17,10 +19,18 @@ class DbServiceFactory implements FactoryInterface
      */
     public function createService(ServiceLocatorInterface $serviceLocator)
     {
-        $user              = $serviceLocator->get('zfcuser_user_service');
-        $config            = $serviceLocator->get('BjyAuthorize\Config');
-        $identityProvider  = new Db($user->getAuthService());
+        $user             = $serviceLocator->get('zfcuser_user_service');
+        $identityProvider = new Db($user->getAuthService());
+
+        $unicaenAppOptions = $serviceLocator->get('unicaen-app_module_options');
+        /* @var $unicaenAppOptions ModuleOptions */
+
+        $ldap = new Ldap($unicaenAppOptions->getLdap()['connection']['default']['params']);
+        $identityProvider->setLdap($ldap);
 
+        $identityProvider->setServiceRole($serviceLocator->get('UnicaenAuth\Service\Role'));
+
+        $config            = $serviceLocator->get('BjyAuthorize\Config');
         $identityProvider->setDefaultRole($config['default_role']);
         $identityProvider->setAuthenticatedRole($config['authenticated_role']);
 
diff --git a/src/UnicaenAuth/Provider/Identity/Ldap.php b/src/UnicaenAuth/Provider/Identity/Ldap.php
index b210db212fb159eb16c6ed5f58089dabbfbeb855..c107a59ed00f7615e50924b36bcd3ef89a0effa6 100644
--- a/src/UnicaenAuth/Provider/Identity/Ldap.php
+++ b/src/UnicaenAuth/Provider/Identity/Ldap.php
@@ -14,6 +14,7 @@ use ZfcUser\Entity\UserInterface;
  * - L'identité authentifiée est fournie par le service d'authentification.
  *
  * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
+ * @deprecated
  */
 class Ldap extends AuthenticationIdentityProvider implements ChainableProvider
 {
diff --git a/src/UnicaenAuth/Provider/Identity/LdapServiceFactory.php b/src/UnicaenAuth/Provider/Identity/LdapServiceFactory.php
index f4b283f82a5ec3ed79983048fe2a083e149578f4..3209e8690bab08d3c8e1f37de37e049297b749dc 100644
--- a/src/UnicaenAuth/Provider/Identity/LdapServiceFactory.php
+++ b/src/UnicaenAuth/Provider/Identity/LdapServiceFactory.php
@@ -15,6 +15,7 @@ class LdapServiceFactory implements FactoryInterface
 {
     /**
      * {@inheritDoc}
+     * @deprecated
      */
     public function createService(ServiceLocatorInterface $serviceLocator)
     {
diff --git a/src/UnicaenAuth/Provider/Privilege/PrivilegeProviderAwareTrait.php b/src/UnicaenAuth/Provider/Privilege/PrivilegeProviderAwareTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..ba6abd90ad0fb5d5c82f4f74c56eb52b1f3debb0
--- /dev/null
+++ b/src/UnicaenAuth/Provider/Privilege/PrivilegeProviderAwareTrait.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace UnicaenAuth\Provider\Privilege;
+
+trait PrivilegeProviderAwareTrait
+{
+    /**
+     * description
+     *
+     * @var PrivilegeProviderInterface
+     */
+    private $privilegeProvider;
+
+    /**
+     *
+     * @param PrivilegeProviderInterface $privilegeProvider
+     * @return self
+     */
+    public function setPrivilegeProvider( PrivilegeProviderInterface $privilegeProvider )
+    {
+        $this->privilegeProvider = $privilegeProvider;
+        return $this;
+    }
+
+    /**
+     *
+     * @return PrivilegeProviderInterface
+     * @throws \Common\Exception\RuntimeException
+     */
+    public function getPrivilegeProvider()
+    {
+        if (empty($this->privilegeProvider)){
+            if (! method_exists($this, 'getServiceLocator')) {
+                throw new \Exception( 'La classe '.get_class($this).' n\'a pas accès au ServiceLocator.');
+            }
+
+            $serviceLocator = $this->getServiceLocator();
+            if (method_exists($serviceLocator, 'getServiceLocator')) {
+                $serviceLocator = $serviceLocator->getServiceLocator();
+            }
+
+            return $serviceLocator->get('UnicaenAuth\Privilege\PrivilegeProvider');
+        }else{
+            return $this->privilegeProvider;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/Provider/Privilege/PrivilegeProviderInterface.php b/src/UnicaenAuth/Provider/Privilege/PrivilegeProviderInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..b5ad26694ce2a7c75394a9a1f1b918b3d3f75e1a
--- /dev/null
+++ b/src/UnicaenAuth/Provider/Privilege/PrivilegeProviderInterface.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace UnicaenAuth\Provider\Privilege;
+
+interface PrivilegeProviderInterface
+{
+
+    /**
+     * Retourne un tableau à deux dimentions composé de chaînes de caractère UNIQUEMENT
+     *
+     * Format du tableau :
+     * [
+     *   'privilege_a' => ['role_1', ...],
+     *   'privilege_b' => ['role_1', 'role_2', ...],
+     * ]
+     *
+     * @return string[][]
+     */
+    public function getPrivilegesRoles();
+
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/Provider/Privilege/Privileges.php b/src/UnicaenAuth/Provider/Privilege/Privileges.php
new file mode 100644
index 0000000000000000000000000000000000000000..5263eaee915582b258e6526f94a7dc26d982982c
--- /dev/null
+++ b/src/UnicaenAuth/Provider/Privilege/Privileges.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace UnicaenAuth\Provider\Privilege;
+
+use UnicaenAuth\Entity\Db\Privilege;
+
+class Privileges {
+
+    const DROIT_ROLE_VISUALISATION          = 'droit-role-visualisation';
+    const DROIT_ROLE_EDITION                = 'droit-role-edition';
+    const DROIT_PRIVILEGE_VISUALISATION     = 'droit-privilege-visualisation';
+    const DROIT_PRIVILEGE_EDITION           = 'droit-privilege-edition';
+
+
+
+    /**
+     * Retourne le nom de la ressource associée au privilège donné
+     *
+     * @param $privilege
+     *
+     * @return string
+     */
+    public static function getResource( $privilege )
+    {
+        if ($privilege instanceof Privilege){
+            $privilege = $privilege->getFullCode();
+        }
+        return 'privilege/'.$privilege;
+    }
+
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/Provider/Role/DbRoleServiceFactory.php b/src/UnicaenAuth/Provider/Role/DbRoleServiceFactory.php
index 26fa008536539c3541818e0684334a520d87b13a..ab238ca040b0336fcfdbc68a1784044eb8c86b21 100644
--- a/src/UnicaenAuth/Provider/Role/DbRoleServiceFactory.php
+++ b/src/UnicaenAuth/Provider/Role/DbRoleServiceFactory.php
@@ -3,6 +3,7 @@
 namespace UnicaenAuth\Provider\Role;
 
 use BjyAuthorize\Exception\InvalidArgumentException;
+use UnicaenAuth\Service\RoleService;
 use Zend\ServiceManager\FactoryInterface;
 use Zend\ServiceManager\ServiceLocatorInterface;
 
@@ -18,27 +19,9 @@ class DbRoleServiceFactory implements FactoryInterface
      */
     public function createService(ServiceLocatorInterface $serviceLocator)
     {
-        $config = $serviceLocator->get('BjyAuthorize\Config');
+        $serviceRole = $serviceLocator->get('UnicaenAuth\Service\Role');
+        /* @var $serviceRole RoleService */
 
-        if (! isset($config['role_providers']['UnicaenAuth\Provider\Role\DbRole'])) {
-            throw new InvalidArgumentException(
-                'Config for "UnicaenAuth\Provider\Role\DbRole" not set'
-            );
-        }
-
-        $providerConfig = $config['role_providers']['UnicaenAuth\Provider\Role\DbRole'];
-
-        if (! isset($providerConfig['role_entity_class'])) {
-            throw new InvalidArgumentException('role_entity_class not set in the bjyauthorize role_providers config.');
-        }
-
-        if (! isset($providerConfig['object_manager'])) {
-            throw new InvalidArgumentException('object_manager not set in the bjyauthorize role_providers config.');
-        }
-
-        /* @var $objectManager \Doctrine\Common\Persistence\ObjectManager */
-        $objectManager = $serviceLocator->get($providerConfig['object_manager']);
-
-        return new DbRole($objectManager->getRepository($providerConfig['role_entity_class']));
+        return new DbRole($serviceRole->getRepo());
     }
 }
diff --git a/src/UnicaenAuth/Provider/Rule/PrivilegeRuleProvider.php b/src/UnicaenAuth/Provider/Rule/PrivilegeRuleProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..99fdba217e97411e03d0ddf996b4b793fd9405bb
--- /dev/null
+++ b/src/UnicaenAuth/Provider/Rule/PrivilegeRuleProvider.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace UnicaenAuth\Provider\Rule;
+
+use BjyAuthorize\Provider\Rule\ProviderInterface;
+use Zend\ServiceManager\ServiceLocatorInterface;
+use Zend\ServiceManager\ServiceLocatorAwareTrait;
+use UnicaenAuth\Provider\Privilege\PrivilegeProviderAwareTrait;
+
+/**
+ * Rule provider based on a given array of rules
+ *
+ * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ */
+class PrivilegeRuleProvider implements ProviderInterface
+{
+    use ServiceLocatorAwareTrait;
+    use PrivilegeProviderAwareTrait;
+
+    /**
+     * @var array
+     */
+    protected $rules;
+
+
+    /**
+     * @param array $config
+     */
+    public function __construct(array $config, ServiceLocatorInterface $serviceLocator)
+    {
+        $this->setServiceLocator($serviceLocator);
+
+        $this->rules = $this->makeRules($config);
+    }
+
+
+
+    public function makeRules(array $config)
+    {
+        $pr = $this->getPrivilegeProvider()->getPrivilegesRoles();
+
+        foreach ($config as $grant => $rules) {
+            foreach ($rules as $index => $rule) {
+                if (is_array($rule)) {
+                    $privileges = (array)$rule['privileges'];
+                    $ressources = $rule['resources'];
+                    $assertion  = isset($rule['assertion']) ? $rule['assertion'] : null;
+                    $bjyRoles   = [];
+                    foreach ($pr as $privilege => $roles) {
+                        if (in_array($privilege, $privileges)) {
+                            $bjyRoles = array_unique(array_merge($bjyRoles, $roles));
+                        }
+                    }
+
+                    $bjyRule = [
+                        $bjyRoles,
+                        $ressources,
+                        $privileges,
+                    ];
+                    if ($assertion) $bjyRule[3] = $assertion;
+
+                    $config[$grant][$index] = $bjyRule;
+                }
+            }
+        }
+        $rules = $config;
+        if (!isset($rules['allow'])) $rules['allow'] = [];
+        foreach ($pr as $privilege => $roles) {
+            $rules['allow'][] = [
+                $roles,
+                'privilege/' . $privilege,
+            ];
+        }
+
+        return $rules;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public function getRules()
+    {
+        return $this->rules;
+    }
+}
diff --git a/src/UnicaenAuth/Service/AbstractService.php b/src/UnicaenAuth/Service/AbstractService.php
new file mode 100644
index 0000000000000000000000000000000000000000..0feb2a0e06f53d94fd4576d85f14eb9fdcfef52c
--- /dev/null
+++ b/src/UnicaenAuth/Service/AbstractService.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace UnicaenAuth\Service;
+
+use UnicaenApp\Service\EntityManagerAwareTrait;
+use UnicaenAuth\Options\ModuleOptions;
+use Zend\ServiceManager\ServiceLocatorAwareInterface;
+use Zend\ServiceManager\ServiceLocatorAwareTrait;
+
+abstract class AbstractService implements ServiceLocatorAwareInterface
+{
+    use ServiceLocatorAwareTrait;
+    use EntityManagerAwareTrait;
+
+    /**
+     * @var \BjyAuthorize\Service\Authorize
+     */
+    private $serviceAuthorize;
+
+
+
+    /**
+     * @return \BjyAuthorize\Service\Authorize
+     */
+    protected function getServiceAuthorize()
+    {
+        if (!$this->serviceAuthorize) {
+            $this->serviceAuthorize = $this->getServiceLocator()->get('BjyAuthorize\Service\Authorize');
+        }
+
+        return $this->serviceAuthorize;
+    }
+
+
+
+    /**
+     * @return \Doctrine\ORM\EntityManager
+     */
+    protected function getEntityManager()
+    {
+        if (!$this->entityManager) {
+            $moduleOptions = $this->getServiceLocator()->get('unicaen-auth_module_options');
+            /* @var $moduleOptions ModuleOptions */
+            $this->entityManager = $this->getServiceLocator()->get($moduleOptions->getEntityManagerName());
+        }
+
+        return $this->entityManager;
+    }
+}
diff --git a/src/UnicaenAuth/Service/AuthorizeService.php b/src/UnicaenAuth/Service/AuthorizeService.php
new file mode 100644
index 0000000000000000000000000000000000000000..c038340c39c02d46dabe12b4efd22b7ae80dc302
--- /dev/null
+++ b/src/UnicaenAuth/Service/AuthorizeService.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * BjyAuthorize Module (https://github.com/bjyoungblood/BjyAuthorize)
+ *
+ * @link https://github.com/bjyoungblood/BjyAuthorize for the canonical source repository
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace UnicaenAuth\Service;
+use UnicaenAuth\Service\Traits\UserContextServiceAwareTrait;
+
+/**
+ * Authorize service
+ *
+ * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ */
+class AuthorizeService extends \BjyAuthorize\Service\Authorize
+{
+    use UserContextServiceAwareTrait;
+
+    /**
+     * Loading...
+     *
+     * @var boolean
+     */
+    protected $loading;
+
+
+    public function getServiceLocator()
+    {
+        return $this->serviceLocator;
+    }
+
+    /**
+     * @deprecated this method will be removed in BjyAuthorize 1.4.x+,
+     *             please retrieve the identity from the
+     *             `BjyAuthorize\Provider\Identity\ProviderInterface` service
+     *
+     * @return string
+     */
+    public function getIdentity()
+    {
+        $this->loaded && $this->loaded->__invoke();
+        if ($this->loading) return 'bjyauthorize-identity';
+        return $this->getServiceUserContext()->getSelectedIdentityRole();
+    }
+
+    /**
+     * Initializes the service
+     *
+     * @internal
+     *
+     * @return void
+     */
+    public function load()
+    {
+        $this->loading = true;
+        parent::load();
+        $this->loading = false;
+    }
+
+}
diff --git a/src/UnicaenAuth/Service/AuthorizeServiceFactory.php b/src/UnicaenAuth/Service/AuthorizeServiceFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..14b7857cc93d06890879e84219030a4c489e1c2d
--- /dev/null
+++ b/src/UnicaenAuth/Service/AuthorizeServiceFactory.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * BjyAuthorize Module (https://github.com/bjyoungblood/BjyAuthorize)
+ *
+ * @link https://github.com/bjyoungblood/BjyAuthorize for the canonical source repository
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace UnicaenAuth\Service;
+
+use Zend\ServiceManager\FactoryInterface;
+use Zend\ServiceManager\ServiceLocatorInterface;
+
+/**
+ * Factory responsible of building the {@see \BjyAuthorize\Service\Authorize} service
+ *
+ * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ */
+class AuthorizeServiceFactory implements FactoryInterface
+{
+    /**
+     * {@inheritDoc}
+     *
+     * @return \Application\Service\Authorize
+     */
+    public function createService(ServiceLocatorInterface $serviceLocator)
+    {
+        return new AuthorizeService($serviceLocator->get('BjyAuthorize\Config'), $serviceLocator);
+    }
+}
diff --git a/src/UnicaenAuth/Service/CategoriePrivilegeService.php b/src/UnicaenAuth/Service/CategoriePrivilegeService.php
new file mode 100644
index 0000000000000000000000000000000000000000..680fa2ec356268e0ddaa01c63133eed483071bbe
--- /dev/null
+++ b/src/UnicaenAuth/Service/CategoriePrivilegeService.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace UnicaenAuth\Service;
+
+use UnicaenAuth\Entity\Db\CategoriePrivilege;
+
+
+class CategoriePrivilegeService extends AbstractService
+{
+
+    /**
+     * @return CategoriePrivilege[]
+     */
+    public function getCategoriesPrivileges()
+    {
+        $dql        = 'SELECT cp FROM UnicaenAuth\Entity\Db\CategoriePrivilege cp ORDER BY cp.ordre';
+        $query      = $this->getEntityManager()->createQuery($dql);
+        $categories = $query->getResult();
+
+        return $categories;
+    }
+
+}
diff --git a/src/UnicaenAuth/Service/PrivilegeService.php b/src/UnicaenAuth/Service/PrivilegeService.php
new file mode 100644
index 0000000000000000000000000000000000000000..5ace3b1325cf034b336764ff8dc03f8d29b773fc
--- /dev/null
+++ b/src/UnicaenAuth/Service/PrivilegeService.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace UnicaenAuth\Service;
+
+use UnicaenAuth\Entity\Db\Privilege;
+use UnicaenAuth\Entity\Db\Role;
+use UnicaenAuth\Provider\Privilege\PrivilegeProviderInterface;
+use \BjyAuthorize\Provider\Resource\ProviderInterface as ResourceProviderInterface;
+
+class PrivilegeService extends AbstractService implements PrivilegeProviderInterface, ResourceProviderInterface
+{
+    /**
+     * @var array
+     */
+    private $privilegesRoles;
+
+
+
+    /**
+     * @return Privilege[]
+     */
+    public function getList()
+    {
+        $dql        = 'SELECT p, c FROM UnicaenAuth\Entity\Db\Privilege p JOIN p.categorie c ORDER BY c.ordre, p.ordre';
+        $query      = $this->getEntityManager()->createQuery($dql);
+        $privileges = $query->getResult();
+
+        return $privileges;
+    }
+
+
+
+    /**
+     * @param $id
+     *
+     * @return null|Privilege
+     */
+    public function get($id)
+    {
+        return $this->getEntityManager()->getRepository('UnicaenAuth\Entity\Db\Privilege')->findOneBy(['id' => $id]);
+    }
+
+
+
+    /**
+     * @param Privilege $privilege
+     * @param Role      $role
+     *
+     * @throws \Doctrine\DBAL\DBALException
+     */
+    public function addRole(Privilege $privilege, Role $role)
+    {
+        $privilege->addRole($role);
+        $this->getEntityManager()->flush();
+    }
+
+
+
+    /**
+     * @param Privilege $privilege
+     * @param Role      $role
+     *
+     * @throws \Doctrine\DBAL\DBALException
+     */
+    public function removeRole(Privilege $privilege, Role $role)
+    {
+        $privilege->removeRole($role);
+        $this->getEntityManager()->flush();
+    }
+
+
+
+    /**
+     * Retourne un tableau à deux dimentions composé de chaînes de caractère UNIQUEMENT
+     *
+     * Format du tableau :
+     * [
+     *   'privilege_a' => ['role_1', ...],
+     *   'privilege_b' => ['role_1', 'role_2', ...],
+     * ]
+     *
+     * @return string[][]
+     */
+    public function getPrivilegesRoles()
+    {
+        if (null === $this->privilegesRoles) {
+            $this->privilegesRoles = [];
+            $dql = '
+            SELECT
+              p, c, r
+            FROM
+              UnicaenAuth\Entity\Db\Privilege p
+              JOIN p.categorie c
+              JOIN p.role r
+            ';
+            $result = $this->getEntityManager()->createQuery($dql)->getResult();
+            foreach( $result as $privilege){
+                /* @var $privilege Privilege */
+                $pr = [];
+                foreach( $privilege->getRole() as $role ){
+                    /* @var $role Role */
+                    $pr[] = $role->getRoleId();
+                }
+                $this->privilegesRoles[$privilege->getFullCode()] = $pr;
+            }
+        }
+
+        return $this->privilegesRoles;
+    }
+
+
+
+    /**
+     * @return array
+     */
+    public function getResources()
+    {
+        $resources  = [];
+        $privileges = array_keys($this->getPrivilegesRoles());
+        foreach ($privileges as $privilege) {
+            $resources[] = 'privilege/' . $privilege;
+        }
+
+        return $resources;
+    }
+
+}
diff --git a/src/UnicaenAuth/Service/RoleService.php b/src/UnicaenAuth/Service/RoleService.php
new file mode 100644
index 0000000000000000000000000000000000000000..162042dd9a966908482262f5e73ebbb500355665
--- /dev/null
+++ b/src/UnicaenAuth/Service/RoleService.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace UnicaenAuth\Service;
+
+use Doctrine\Common\Persistence\ObjectRepository;
+use UnicaenAuth\Entity\Db\Role;
+
+
+/**
+ * Class RoleService
+ *
+ * @package UnicaenAuth\Service
+ * @author  Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ */
+class RoleService extends AbstractService
+{
+    /**
+     * @return ObjectRepository
+     */
+    public function getRepo()
+    {
+        return $this->getEntityManager()->getRepository('UnicaenAuth\Entity\Db\Role');
+    }
+
+
+
+    /**
+     * @return Role[]
+     */
+    public function getList()
+    {
+        $dql   = 'SELECT r FROM UnicaenAuth\Entity\Db\Role r ORDER BY r.roleId';
+        $query = $this->getEntityManager()->createQuery($dql);
+        $roles = $query->getResult();
+
+        return $roles;
+    }
+
+
+
+    /**
+     * @param $id
+     *
+     * @return null|Role
+     */
+    public function get($id)
+    {
+        return $this->getRepo()->findOneBy(['id' => $id]);
+    }
+
+
+
+    /**
+     * Sauvegarde le rôle en BDD
+     *
+     * @param Role $role
+     *
+     * @return self
+     */
+    public function save(Role $role)
+    {
+        $this->getEntityManager()->persist($role);
+        $this->getEntityManager()->flush($role);
+
+        return $this;
+    }
+
+
+
+    /**
+     * Supprime un rôle
+     *
+     * @param Role $role
+     *
+     * @return $this
+     */
+    public function delete(Role $role)
+    {
+        $this->getEntityManager()->remove($role);
+        $this->getEntityManager()->flush($role);
+
+        return $this;
+    }
+
+
+
+    /**
+     * Nouvelle entité
+     *
+     * @return Role
+     */
+    public function newEntity()
+    {
+        return new Role;
+    }
+}
diff --git a/src/UnicaenAuth/Service/Traits/CategoriePrivilegeAwareTrait.php b/src/UnicaenAuth/Service/Traits/CategoriePrivilegeAwareTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..19a75df27609041ec09539138c5c3ae8212b27b5
--- /dev/null
+++ b/src/UnicaenAuth/Service/Traits/CategoriePrivilegeAwareTrait.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace UnicaenAuth\Service\Traits;
+
+use UnicaenAuth\Service\CategoriePrivilegeService;
+use RuntimeException;
+
+/**
+ * Description of CategoriePrivilegeServiceAwareTrait
+ *
+ * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ */
+trait CategoriePrivilegeServiceAwareTrait
+{
+    /**
+     * @var CategoriePrivilegeService
+     */
+    private $serviceCategoriePrivilege;
+
+
+
+    /**
+     * @param CategoriePrivilegeService $serviceCategoriePrivilege
+     *
+     * @return self
+     */
+    public function setServiceCategoriePrivilege(CategoriePrivilegeService $serviceCategoriePrivilege)
+    {
+        $this->serviceCategoriePrivilege = $serviceCategoriePrivilege;
+
+        return $this;
+    }
+
+
+
+    /**
+     * @return CategoriePrivilegeService
+     * @throws RuntimeException
+     */
+    public function getServiceCategoriePrivilege()
+    {
+        if (empty($this->serviceCategoriePrivilege)) {
+            if (!method_exists($this, 'getServiceLocator')) {
+                throw new RuntimeException('La classe ' . get_class($this) . ' n\'a pas accès au ServiceLocator.');
+            }
+
+            $serviceLocator = $this->getServiceLocator();
+            if (method_exists($serviceLocator, 'getServiceLocator')) {
+                $serviceLocator = $serviceLocator->getServiceLocator();
+            }
+            $this->serviceCategoriePrivilege = $serviceLocator->get('UnicaenAuth\Service\CategoriePrivilege');
+        }
+
+        return $this->serviceCategoriePrivilege;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/Service/Traits/PrivilegeServiceAwareTrait.php b/src/UnicaenAuth/Service/Traits/PrivilegeServiceAwareTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..e26587946fc368239edc38284032fe7b34da1791
--- /dev/null
+++ b/src/UnicaenAuth/Service/Traits/PrivilegeServiceAwareTrait.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace UnicaenAuth\Service\Traits;
+
+use UnicaenAuth\Service\PrivilegeService;
+use RuntimeException;
+
+/**
+ * Description of PrivilegeServiceAwareTrait
+ *
+ * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ */
+trait PrivilegeServiceAwareTrait
+{
+    /**
+     * @var PrivilegeService
+     */
+    private $servicePrivilege;
+
+
+
+    /**
+     * @param PrivilegeService $servicePrivilege
+     *
+     * @return self
+     */
+    public function setServicePrivilege(PrivilegeService $servicePrivilege)
+    {
+        $this->servicePrivilege = $servicePrivilege;
+
+        return $this;
+    }
+
+
+
+    /**
+     * @return PrivilegeService
+     * @throws RuntimeException
+     */
+    public function getServicePrivilege()
+    {
+        if (empty($this->servicePrivilege)) {
+            if (!method_exists($this, 'getServiceLocator')) {
+                throw new RuntimeException('La classe ' . get_class($this) . ' n\'a pas accès au ServiceLocator.');
+            }
+
+            $serviceLocator = $this->getServiceLocator();
+            if (method_exists($serviceLocator, 'getServiceLocator')) {
+                $serviceLocator = $serviceLocator->getServiceLocator();
+            }
+            $this->servicePrivilege = $serviceLocator->get('UnicaenAuth\Service\Privilege');
+        }
+
+        return $this->servicePrivilege;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/Service/Traits/RoleServiceAwareTrait.php b/src/UnicaenAuth/Service/Traits/RoleServiceAwareTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..57cb0127d2b94f8eb3c4ca1f9b517e620de250ff
--- /dev/null
+++ b/src/UnicaenAuth/Service/Traits/RoleServiceAwareTrait.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace UnicaenAuth\Service\Traits;
+
+use UnicaenAuth\Service\RoleService;
+use RuntimeException;
+
+/**
+ * Description of RoleServiceAwareTrait
+ *
+ * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ */
+trait RoleServiceAwareTrait
+{
+    /**
+     * @var RoleService
+     */
+    private $serviceRole;
+
+
+
+    /**
+     * @param RoleService $serviceRole
+     *
+     * @return self
+     */
+    public function setServiceRole(RoleService $serviceRole)
+    {
+        $this->serviceRole = $serviceRole;
+
+        return $this;
+    }
+
+
+
+    /**
+     * @return RoleService
+     * @throws RuntimeException
+     */
+    public function getServiceRole()
+    {
+        if (empty($this->serviceRole)) {
+            if (!method_exists($this, 'getServiceLocator')) {
+                throw new RuntimeException('La classe ' . get_class($this) . ' n\'a pas accès au ServiceLocator.');
+            }
+
+            $serviceLocator = $this->getServiceLocator();
+            if (method_exists($serviceLocator, 'getServiceLocator')) {
+                $serviceLocator = $serviceLocator->getServiceLocator();
+            }
+            $this->serviceRole = $serviceLocator->get('UnicaenAuth\Service\Role');
+        }
+
+        return $this->serviceRole;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/Service/Traits/UserContextServiceAwareTrait.php b/src/UnicaenAuth/Service/Traits/UserContextServiceAwareTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..8e958bb64091030e493a4658475595ec0e03d294
--- /dev/null
+++ b/src/UnicaenAuth/Service/Traits/UserContextServiceAwareTrait.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace UnicaenAuth\Service\Traits;
+
+use UnicaenAuth\Service\UserContextService;
+use RuntimeException;
+
+/**
+ * Description of UserContextServiceAwareTrait
+ *
+ * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ */
+trait UserContextServiceAwareTrait
+{
+    /**
+     * @var UserContextService
+     */
+    private $serviceUserContext;
+
+
+
+    /**
+     * @param UserContextService $serviceUserContext
+     *
+     * @return self
+     */
+    public function setServiceUserContext(UserContextService $serviceUserContext)
+    {
+        $this->serviceUserContext = $serviceUserContext;
+
+        return $this;
+    }
+
+
+
+    /**
+     * @return UserContextService
+     * @throws RuntimeException
+     */
+    public function getServiceUserContext()
+    {
+        if (empty($this->serviceUserContext)) {
+            if (!method_exists($this, 'getServiceLocator')) {
+                throw new RuntimeException('La classe ' . get_class($this) . ' n\'a pas accès au ServiceLocator.');
+            }
+
+            $serviceLocator = $this->getServiceLocator();
+            if (method_exists($serviceLocator, 'getServiceLocator')) {
+                $serviceLocator = $serviceLocator->getServiceLocator();
+            }
+            $this->serviceUserContext = $serviceLocator->get('UnicaenAuth\Service\UserContext');
+        }
+
+        return $this->serviceUserContext;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/Service/User.php b/src/UnicaenAuth/Service/User.php
index f10946f325bd24eeec67c8db45d43a401bb50a4f..34386146ba75c8191f59034ae83d4a1a82ccd7cf 100644
--- a/src/UnicaenAuth/Service/User.php
+++ b/src/UnicaenAuth/Service/User.php
@@ -6,6 +6,8 @@ use UnicaenApp\Exception;
 use UnicaenApp\Mapper\Ldap\People as LdapPeopleMapper;
 use UnicaenAuth\Options\ModuleOptions;
 use UnicaenAuth\Event\UserAuthenticatedEvent;
+use Zend\ServiceManager\ServiceLocatorAwareInterface;
+use Zend\ServiceManager\ServiceLocatorAwareTrait;
 use Zend\ServiceManager\ServiceManager;
 use Zend\ServiceManager\ServiceManagerAwareInterface;
 use Zend\EventManager\EventManagerAwareInterface;
@@ -24,14 +26,12 @@ use ZfcUser\Options\ModuleOptions as ZfcUserModuleOptions;
  * @see \UnicaenAuth\Authentication\Adapter\AbstractFactory
  * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
  */
-class User implements ServiceManagerAwareInterface, EventManagerAwareInterface
+class User implements ServiceLocatorAwareInterface, EventManagerAwareInterface
 {
-    const EVENT_USER_AUTHENTICATED_PRE_PERSIST = 'userAuthenticated.prePersist';
+    use ServiceLocatorAwareTrait;
 
-    /**
-     * @var ServiceManager
-     */
-    protected $serviceManager;
+
+    const EVENT_USER_AUTHENTICATED_PRE_PERSIST = 'userAuthenticated.prePersist';
 
     /**
      * @var EventManagerInterface
@@ -83,7 +83,7 @@ class User implements ServiceManagerAwareInterface, EventManagerAwareInterface
         }
 
         // update/insert de l'utilisateur dans la table de l'appli
-        $mapper = $this->getServiceManager()->get('zfcuser_user_mapper'); /* @var $mapper \ZfcUserDoctrineORM\Mapper\User */
+        $mapper = $this->getServiceLocator()->get('zfcuser_user_mapper'); /* @var $mapper \ZfcUserDoctrineORM\Mapper\User */
         try {
             $entity = $mapper->findByUsername($username);
             if (!$entity) {
@@ -119,26 +119,6 @@ class User implements ServiceManagerAwareInterface, EventManagerAwareInterface
         return true;
     }
 
-    /**
-     * Retrieve service manager instance
-     *
-     * @return ServiceManager
-     */
-    public function getServiceManager()
-    {
-        return $this->serviceManager;
-    }
-
-    /**
-     * Set service manager
-     *
-     * @param ServiceManager $serviceManager
-     */
-    public function setServiceManager(ServiceManager $serviceManager)
-    {
-        $this->serviceManager = $serviceManager;
-        return $this;
-    }
 
     /**
      * Retrieve the event manager
@@ -176,7 +156,7 @@ class User implements ServiceManagerAwareInterface, EventManagerAwareInterface
     public function getLdapPeopleMapper()
     {
         if (null === $this->ldapPeopleMapper) {
-            $this->ldapPeopleMapper = $this->getServiceManager()->get('ldap_people_mapper');
+            $this->ldapPeopleMapper = $this->getServiceLocator()->get('ldap_people_mapper');
         }
         return $this->ldapPeopleMapper;
     }
@@ -208,7 +188,7 @@ class User implements ServiceManagerAwareInterface, EventManagerAwareInterface
     public function getOptions()
     {
         if (!$this->options instanceof ModuleOptions) {
-            $this->setOptions($this->getServiceManager()->get('unicaen-auth_module_options'));
+            $this->setOptions($this->getServiceLocator()->get('unicaen-auth_module_options'));
         }
         return $this->options;
     }
diff --git a/src/UnicaenAuth/Service/UserContext.php b/src/UnicaenAuth/Service/UserContext.php
index df9d395f9be8bca632b151a68d1262377df8fa15..a07398f34d6b3290be1bd3a28a6b5d49ac5ff19a 100644
--- a/src/UnicaenAuth/Service/UserContext.php
+++ b/src/UnicaenAuth/Service/UserContext.php
@@ -3,8 +3,7 @@
 namespace UnicaenAuth\Service;
 
 use UnicaenApp\Exception\RuntimeException;
-use Zend\ServiceManager\ServiceLocatorAwareInterface;
-use Zend\ServiceManager\ServiceLocatorAwareTrait;
+use UnicaenApp\Traits\SessionContainerTrait;
 use Zend\Session\Container as SessionContainer;
 use Zend\Permissions\Acl\Role\RoleInterface;
 use ZfcUser\Entity\UserInterface;
@@ -16,9 +15,9 @@ use UnicaenAuth\Acl\NamedRole;
  *
  * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
  */
-class UserContext implements ServiceLocatorAwareInterface
+class UserContext extends AbstractService
 {
-    use ServiceLocatorAwareTrait;
+    use SessionContainerTrait;
 
     /**
      * @var mixed
@@ -30,10 +29,7 @@ class UserContext implements ServiceLocatorAwareInterface
      */
     protected $identityRoles;
 
-    /**
-     * @var SessionContainer
-     */
-    protected $sessionContainer;
+
 
     /**
      * Retourne l'utilisateur BDD courant
@@ -51,6 +47,8 @@ class UserContext implements ServiceLocatorAwareInterface
         return null;
     }
 
+
+
     /**
      * Retourne l'utilisateur LDAP courant
      *
@@ -67,6 +65,8 @@ class UserContext implements ServiceLocatorAwareInterface
         return null;
     }
 
+
+
     /**
      * Retourne les données d'identité correspondant à l'utilisateur courant.
      *
@@ -84,6 +84,8 @@ class UserContext implements ServiceLocatorAwareInterface
         return $this->identity;
     }
 
+
+
     /**
      * Retourne tous les rôles de l'utilisateur courant, pas seulement le rôle courant sélectionné.
      *
@@ -92,13 +94,15 @@ class UserContext implements ServiceLocatorAwareInterface
     public function getIdentityRoles()
     {
         if (null === $this->identityRoles) {
-            $identityProvider = $this->getIdentityProvider();
+            $identityProvider    = $this->getIdentityProvider();
             $this->identityRoles = $identityProvider->getAllIdentityRoles();
         }
 
         return $this->identityRoles;
     }
 
+
+
     /**
      * Retourne parmi tous les rôles de l'utilisateur courant ceux qui peuvent être sélectionnés.
      *
@@ -106,12 +110,16 @@ class UserContext implements ServiceLocatorAwareInterface
      */
     public function getSelectableIdentityRoles()
     {
-        $filter = function($r) { return !($r instanceof NamedRole && !$r->getSelectable()); };
+        $filter = function ($r) {
+            return !($r instanceof NamedRole && !$r->getSelectable());
+        };
         $roles  = array_filter($this->getIdentityRoles(), $filter);
 
         return $roles;
     }
 
+
+
     /**
      * Si un utilisateur est authentifié, retourne le rôle utilisateur sélectionné,
      * ou alors le premier sélectionnable si aucun n'a été sélectionné.
@@ -134,20 +142,25 @@ class UserContext implements ServiceLocatorAwareInterface
 
         $roleId = $this->getSessionContainer()->selectedIdentityRole;
 
-        $role = $this->normalizedIdentityRole($roleId);
-        if ($this->isRoleValid($role)) {
-            return $role;
+        if ($roleId){
+            $role = $this->normalizedIdentityRole($roleId);
+            if ($this->isRoleValid($role)) {
+                return $role;
+            }
         }
 
         return null;
     }
 
+
+
     /**
      * Mémorise en session le rôle spécifié comme étant le rôle courant de l'utilisateur.
      *
      * NB: seul l'id du rôle est mémorisé en session.
      *
      * @param RoleInterface|string $role
+     *
      * @return \UnicaenAuth\Service\UserContext
      * @throws RuntimeException
      */
@@ -161,30 +174,34 @@ class UserContext implements ServiceLocatorAwareInterface
                 $role = $role->getRoleId();
             }
             $this->getSessionContainer()->selectedIdentityRole = $role;
-        }
-        else {
+        } else {
             unset($this->getSessionContainer()->selectedIdentityRole);
         }
 
         return $this;
     }
 
+
+
     /**
      * Retourne l'éventuel rôle spécifié en session devant être le prochain rôle sélectionné.
      *
      * @return string|null
      */
-    private function getNextSelectedIdentityRole()
+    public function getNextSelectedIdentityRole()
     {
         return $this->getSessionContainer()->nextSelectedIdentityRole;
     }
 
+
+
     /**
      * Mémorise en session le rôle devant être le prochain rôle sélectionné.
      *
      * NB: seul l'id du rôle est mémorisé en session ; la durée de vie du stockage est de 1 requête seulement.
      *
      * @param RoleInterface|string $role
+     *
      * @return \UnicaenAuth\Service\UserContext
      */
     public function setNextSelectedIdentityRole($role)
@@ -196,19 +213,20 @@ class UserContext implements ServiceLocatorAwareInterface
         if ($role) {
             $this->getSessionContainer()->nextSelectedIdentityRole = $role;
             $this->getSessionContainer()->setExpirationHops(1, 'nextSelectedIdentityRole');
-
-        }
-        else {
+        } else {
             unset($this->getSessionContainer()->nextSelectedIdentityRole);
         }
 
         return $this;
     }
 
+
+
     /**
      * Recherche le role spécifié parmi les rôles connus au format objets.
      *
      * @param RoleInterface|string $role
+     *
      * @return RoleInterface Role trouvé au format objet dans la mesure du possible
      */
     protected function normalizedIdentityRole($role)
@@ -229,10 +247,13 @@ class UserContext implements ServiceLocatorAwareInterface
         return $role;
     }
 
+
+
     /**
      * Teste si le rôle spécifié fait partie des rôles disponibles.
      *
      * @param RoleInterface|string $role
+     *
      * @return boolean
      */
     protected function isRoleValid($role)
@@ -253,29 +274,16 @@ class UserContext implements ServiceLocatorAwareInterface
         return false;
     }
 
+
+
     /**
      *
      * @return \UnicaenAuth\Provider\Identity\Chain
      */
     private function getIdentityProvider()
     {
-        $authorize = $this->getServiceLocator()->get('BjyAuthorize\Service\Authorize');
-
-        return $authorize->getIdentityProvider(); /* @var $identityProvider \UnicaenAuth\Provider\Identity\Chain */
+        return $this->getServiceAuthorize()->getIdentityProvider();
+        /* @var $identityProvider \UnicaenAuth\Provider\Identity\Chain */
     }
 
-    /**
-     * Retourne le stockage en session utilisé pour mémoriser le profil
-     * sélectionné par l'utilsateur.
-     *
-     * @return SessionContainer
-     */
-    protected function getSessionContainer()
-    {
-        if (null === $this->sessionContainer) {
-            $this->sessionContainer = new SessionContainer(get_class());
-        }
-
-        return $this->sessionContainer;
-    }
 }
\ No newline at end of file
diff --git a/view/unicaen-auth/droits/index.phtml b/view/unicaen-auth/droits/index.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..3f1837029d85638dbe083abc02a1604922b43bf9
--- /dev/null
+++ b/view/unicaen-auth/droits/index.phtml
@@ -0,0 +1,34 @@
+<?php
+
+use UnicaenAuth\Provider\Privilege\Privileges;
+
+$canViewRoles      = $this->isAllowed(Privileges::getResource(Privileges::DROIT_ROLE_VISUALISATION));
+$canViewPrivileges = $this->isAllowed(Privileges::getResource(Privileges::DROIT_PRIVILEGE_VISUALISATION));
+
+?>
+<h1 class="page-header">Gestion des droits d'accès</h1>
+
+<dl>
+    <?php if ($canViewRoles): ?>
+        <dt><a href="<?php echo $this->url('droits/roles') ?>">Gestion des rôles</a></dt>
+        <dd>
+            Permet de visualiser les rôles existants. Permet également de les modifier,
+            d'en ajouter ou d'en supprimer si vous avez les droits requis pour cela.
+        </dd>
+    <?php endif; ?>
+
+    <?php if ($canViewPrivileges): ?>
+        <dt><a href="<?php echo $this->url('droits/privileges') ?>">Gestion des privilèges</a></dt>
+        <dd>
+            Tableau de bord listant, par rôle, les privilèges qui lui sont accordés.
+            Le tableau permet également, si vous en avez le droit, de modifier les privilèges accordés par rôle.
+        </dd>
+    <?php endif; ?>
+</dl>
+<style>
+
+    dt {
+        padding-top: 2em;
+    }
+
+</style>
\ No newline at end of file
diff --git a/view/unicaen-auth/droits/partial/tbl-link.phtml b/view/unicaen-auth/droits/partial/tbl-link.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..254869740a36ce298fed47e73d8d0bb72ea6adff
--- /dev/null
+++ b/view/unicaen-auth/droits/partial/tbl-link.phtml
@@ -0,0 +1,23 @@
+<?php
+
+use UnicaenAuth\Provider\Privilege\Privileges;
+
+/* @var $role UnicaenAuth\Entity\Db\Role */
+/* @var $privilege UnicaenAuth\Entity\Db\Privilege */
+
+$canEdit = $this->isAllowed('privilege/'.Privileges::DROIT_PRIVILEGE_EDITION);
+
+if ($privilege->getRole()->contains($role)):
+?>
+
+    <?php if ($canEdit): ?><a href="javascript:void(0)" data-action="refuser" title="Privilège accordé. Cliquez pour le retirer."><?php endif; ?>
+        <span class="glyphicon glyphicon-ok text-success"></span>
+    <?php if ($canEdit): ?></a><?php endif; ?>
+
+<?php else: ?>
+
+    <?php if ($canEdit): ?><a href="javascript:void(0)" data-action="accorder" title="Privilège refusé. Cliquez pour l'accorder."><?php endif; ?>
+        <span class="glyphicon glyphicon-remove text-danger refuse"></span>
+    <?php if ($canEdit): ?></a><?php endif; ?>
+
+<?php endif; ?>
\ No newline at end of file
diff --git a/view/unicaen-auth/droits/privileges-modifier.phtml b/view/unicaen-auth/droits/privileges-modifier.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..1e994398040b46a1831413f46409f62ad1e564e2
--- /dev/null
+++ b/view/unicaen-auth/droits/privileges-modifier.phtml
@@ -0,0 +1,9 @@
+<?php
+
+/* @var $role UnicaenAuth\Entity\Db\Role */
+/* @var $privilege UnicaenAuth\Entity\Db\Privilege */
+
+echo $this->partial(
+        '/unicaen-auth/droits/partial/tbl-link',
+        compact('role','privilege')
+     );
\ No newline at end of file
diff --git a/view/unicaen-auth/droits/privileges.phtml b/view/unicaen-auth/droits/privileges.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..8ce8e3ec1786b06180d441b15e77a29a045addf6
--- /dev/null
+++ b/view/unicaen-auth/droits/privileges.phtml
@@ -0,0 +1,152 @@
+<?php
+
+/* @var $privileges UnicaenAuth\Entity\Db\Privilege[] */
+/* @var $roles UnicaenAuth\Entity\Db\Role[] */
+
+?>
+<h1 class="page-header">Gestion des privilèges</h1>
+
+<table class="droits-tbl table table-hover table-bordered table-condensed table-extra-condensed table-header-rotated" data-modifier-url="<?php echo $this->url('droits/privileges/modifier'); ?>">
+<thead>
+    <tr>
+        <th class="separator"></th>
+    <?php $first = true; foreach( $roles as $role ):?>
+        <th class="rotate-45" title="<?php echo $role; ?>"><div<?php if ($first) echo ' class="first"'; ?>><span><?php echo $role; ?></span></div></th>
+    <?php $first = false; endforeach; ?>
+    </tr>
+    <tr>
+        <th>Privilèges</th>
+        <th colspan="<?php echo count($roles); ?>">Rôles</th>
+        <th style="border:none;min-width:166px">&nbsp;</th>
+    </tr>
+</thead>
+<tbody>
+<?php foreach( $privileges as $cat ): ?>
+    <tr>
+        <th class="separator">&nbsp;</th>
+        <th class="separator" colspan="<?php echo 1 + count($roles); ?>"><?php echo $cat['categorie'] ?></th>
+    </tr>
+    <?php foreach( $cat['privileges'] as $privilege ): ?>
+    <tr>
+        <th class="privilege"><?php echo $privilege ?></th>
+        <?php $statut=null; foreach( $roles as $role ): ?>
+            <td class="modifier" data-role="<?php echo $role->getId() ?>" data-privilege="<?php echo $privilege->getId() ?>">
+            <?php echo $this->partial( '/unicaen-auth/droits/partial/tbl-link', compact('role','privilege')) ?>
+            </td>
+        <?php endforeach; ?>
+    </tr>
+    <?php endforeach; ?>
+<?php endforeach; ?>
+</tbody>
+</table>
+<script>
+    $(function ()
+    {
+        $.widget("ose.droitsTbl", {
+
+            modifier: function (td, action)
+            {
+                var that = this;
+                td.html("<div class=\"loading\">&nbsp;</div>");
+                td.load(this.element.data('modifier-url'), {
+                    role: td.data("role"),
+                    statut: td.data("statut"),
+                    privilege: td.data("privilege"),
+                    action: action
+                }, function ()
+                {
+                    that.initModifierClick(td); // pour reconnecter l'action du lien...
+                });
+
+            },
+
+
+            initModifierClick: function (td)
+            {
+                var that = this;
+                td.find("a").on("click", function ()
+                {
+                    that.modifier(td, $(this).data("action"));
+                });
+            },
+
+            _create: function ()
+            {
+                var that = this;
+                this.element.find("td.modifier").each(function ()
+                {
+                    that.initModifierClick($(this));
+                });
+            }
+        });
+
+        WidgetInitializer.add('droits-tbl', 'droitsTbl');
+    });
+
+</script>
+<style>
+
+    .table-header-rotated th.row-header {
+        width: auto;
+
+    }
+
+    .table-header-rotated td {
+        width: 40px;
+        vertical-align: middle;
+        text-align: center;
+    }
+
+    .table-header-rotated th.rotate-45 {
+        border: none;
+        height: 200px;
+        width: 40px;
+        min-width: 40px;
+        max-width: 40px;
+        position: relative;
+        vertical-align: bottom;
+        padding: 0;
+        line-height: 1;
+        white-space: nowrap;
+    }
+
+    .table-header-rotated th.rotate-45 > div {
+        position: relative;
+        top: 0px;
+        left: 83px;
+        height: 100%;
+        transform: skew(-40deg, 0deg);
+        overflow: hidden;
+        border-right: 1px solid #ddd;
+    }
+
+    .table-header-rotated th.rotate-45 > div.first {
+        border-left: 1px solid #ddd;
+    }
+
+    .table-header-rotated th.rotate-45 span {
+        transform: skew(40deg, 0deg) rotate(310deg);
+        position: absolute;
+        bottom: 40px;
+        left: -30px;
+        display: inline-block;
+        width: 100px;
+        text-align: left;
+    }
+
+    .table-header-rotated .separator {
+        border: none;
+    }
+
+    .droits-tbl th.privilege {
+        min-width: 200px;
+        max-width: 200px;
+        width: 200px;
+    }
+
+    .droits-tbl td span.refuse {
+        opacity: 0.5;
+    }
+
+
+</style>
\ No newline at end of file
diff --git a/view/unicaen-auth/droits/role-edition.phtml b/view/unicaen-auth/droits/role-edition.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..e7699d422c69ab4815f80eb41cb04da64706147a
--- /dev/null
+++ b/view/unicaen-auth/droits/role-edition.phtml
@@ -0,0 +1,19 @@
+<?php
+
+/* @var $form Application\Form\Gestion\RoleForm */
+/* @var $errors array */
+
+
+echo $this->form()->openTag($form->prepare());
+
+if ($errors) {
+    echo $this->messenger()->setMessages([UnicaenApp\View\Helper\Messenger::ERROR => $errors]);
+}
+
+echo $this->formControlGroup($form->get('role-id'));
+echo $this->formControlGroup($form->get('parent'));
+echo $this->formControlGroup($form->get('ldap-filter'));
+echo $this->formRow($form->get('submit'));
+echo $this->formHidden($form->get('id'));
+
+echo $this->form()->closeTag();
\ No newline at end of file
diff --git a/view/unicaen-auth/droits/role-suppression.phtml b/view/unicaen-auth/droits/role-suppression.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..9939d8dae5237d0392f7437998c4289771468728
--- /dev/null
+++ b/view/unicaen-auth/droits/role-suppression.phtml
@@ -0,0 +1,12 @@
+<?php
+if (isset($errors) && $errors) {
+    echo $this->messenger()->setMessages([UnicaenApp\View\Helper\Messenger::ERROR => $errors]);
+}
+else {
+    echo '<p class="lead text-danger"><strong>Attention!</strong> Confirmez-vous la suppression du rôle '.$role.' ?</p>';
+
+    echo $this->form()->openTag($form);
+    echo $this->formHidden($form->get('id'));
+    echo $this->formSubmit($form->get('submit')->setAttribute('class', 'btn btn-primary'));
+    echo $this->form()->closeTag();
+}
\ No newline at end of file
diff --git a/view/unicaen-auth/droits/roles.phtml b/view/unicaen-auth/droits/roles.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..ed85487cd53eff421b4fcc818b7620b4970301e9
--- /dev/null
+++ b/view/unicaen-auth/droits/roles.phtml
@@ -0,0 +1,50 @@
+<h1 class="page-header">Gestion des rôles</h1>
+<?php
+
+use UnicaenAuth\Provider\Privilege\Privileges;
+
+/* @var $roles UnicaenAuth\Entity\Db\Role[] */
+
+$canEdit = $this->isAllowed('privilege/'.Privileges::DROIT_ROLE_EDITION);
+$ajoutUrl = $this->url( 'droits/roles/edition' );
+
+?>
+<table class="table table-condensed table-bordered">
+    <tr>
+        <th>Nom</th>
+        <th>Parent</th>
+        <th>Filtre LDAP</th>
+        <?php if ($canEdit): ?><th>Action</th><?php endif; ?>
+    </tr>
+<?php foreach( $roles as $role ):
+    $editionUrl     = $this->url( 'droits/roles/edition',     ['role' => $role->getId()] );
+    $suppressionUrl = $this->url( 'droits/roles/suppression', ['role' => $role->getId()] );
+?>
+    <tr>
+        <td><?php echo $role->getRoleId(); ?></td>
+        <td><?php echo $role->getParent(); ?></td>
+        <td><?php echo $role->getLdapFilter(); ?></td>
+        <?php if ($canEdit): ?>
+        <td style="width:1%;white-space: nowrap;text-align: center">
+            <a href="<?php echo $editionUrl; ?>" class="ajax-modal" data-event="role-edition"><span class="glyphicon glyphicon-edit"></span></a>
+            <a href="<?php echo $suppressionUrl; ?>" class="ajax-modal" data-event="role-suppression"><span class="glyphicon glyphicon-remove"></span></a>
+        </td>
+        <?php endif; ?>
+    </tr>
+<?php endforeach; ?>
+</table>
+<?php if ($canEdit): // droits ?>
+<a href="<?php echo $ajoutUrl ?>" class="btn btn-primary ajax-modal" data-event="role-edition">Création d'un nouveau rôle</a>
+<?php endif; ?>
+<?php echo $this->modalAjaxDialog('roles-edition-suppression'); ?>
+<script type="text/javascript">
+    $(function() {
+        $("body").on("role-edition", function(event, data) {
+            window.location.reload();
+        });
+
+        $("body").on("role-suppression", function(event, data) {
+            window.location.reload();
+        });
+    });
+</script>
\ No newline at end of file