diff --git a/rest/index.php b/rest/index.php
index 8968cb88255cc31ef75cca8e315fe78bb4c01a0e..6e78de30eea9777c619bbfa0bfda74ff4a7cfc09 100755
--- a/rest/index.php
+++ b/rest/index.php
@@ -33,18 +33,20 @@ $app->add(function (\Slim\Http\Request $request, \Slim\Http\Response $response,
     $currentMethod = empty($route) ? '' : $route->getMethods()[0];
     $currentRoute = empty($route) ? '' : $route->getPattern();
     if (!in_array($currentMethod.$currentRoute, \SrcCore\controllers\AuthenticationController::ROUTES_WITHOUT_AUTHENTICATION)) {
-        $authorizationHeaders = $request->getHeader('Authorization');
-        $userId = \SrcCore\controllers\AuthenticationController::authentication($authorizationHeaders);
-        if (!empty($userId)) {
-            \SrcCore\controllers\CoreController::setGlobals(['userId' => $userId]);
-            if (!empty($currentRoute)) {
-                $r = \SrcCore\controllers\AuthenticationController::isRouteAvailable(['userId' => $userId, 'currentRoute' => $currentRoute, 'currentMethod' => $currentMethod]);
-                if (!$r['isRouteAvailable']) {
-                    return $response->withStatus(403)->withJson(['errors' => $r['errors']]);
+        if (!\SrcCore\controllers\AuthenticationController::canAccessInstallerWhitoutAuthentication(['route' => $currentMethod.$currentRoute])) {
+            $authorizationHeaders = $request->getHeader('Authorization');
+            $userId = \SrcCore\controllers\AuthenticationController::authentication($authorizationHeaders);
+            if (!empty($userId)) {
+                \SrcCore\controllers\CoreController::setGlobals(['userId' => $userId]);
+                if (!empty($currentRoute)) {
+                    $r = \SrcCore\controllers\AuthenticationController::isRouteAvailable(['userId' => $userId, 'currentRoute' => $currentRoute, 'currentMethod' => $currentMethod]);
+                    if (!$r['isRouteAvailable']) {
+                        return $response->withStatus(403)->withJson(['errors' => $r['errors']]);
+                    }
                 }
+            } else {
+                return $response->withStatus(401)->withJson(['errors' => 'Authentication Failed']);
             }
-        } else {
-            return $response->withStatus(401)->withJson(['errors' => 'Authentication Failed']);
         }
     }
     $response = $next($request, $response);
@@ -320,6 +322,7 @@ $app->get('/installer/databaseConnection', \SrcCore\controllers\InstallerControl
 $app->get('/installer/sqlDataFiles', \SrcCore\controllers\InstallerController::class . ':getSQLDataFiles');
 $app->get('/installer/docservers', \SrcCore\controllers\InstallerController::class . ':checkDocservers');
 $app->get('/installer/custom', \SrcCore\controllers\InstallerController::class . ':checkCustomName');
+$app->get('/installer/customs', \SrcCore\controllers\InstallerController::class . ':getCustoms');
 $app->post('/installer/custom', \SrcCore\controllers\InstallerController::class . ':createCustom');
 $app->post('/installer/database', \SrcCore\controllers\InstallerController::class . ':createDatabase');
 $app->post('/installer/docservers', \SrcCore\controllers\InstallerController::class . ':createDocservers');
diff --git a/src/core/controllers/AuthenticationController.php b/src/core/controllers/AuthenticationController.php
index 9ba9613bea677ca3072ad73b01964384a9de1003..5c0e58e1739f29a87ce804637b6bebcdc9be2bc6 100755
--- a/src/core/controllers/AuthenticationController.php
+++ b/src/core/controllers/AuthenticationController.php
@@ -35,10 +35,7 @@ class AuthenticationController
     const ROUTES_WITHOUT_AUTHENTICATION = [
         'GET/authenticationInformations', 'PUT/versionsUpdateSQL', 'GET/validUrl', 'GET/authenticate/token', 'GET/images', 'POST/password', 'PUT/password', 'GET/passwordRules',
         'GET/jnlp/{jnlpUniqueId}', 'GET/onlyOffice/mergedFile', 'POST/onlyOfficeCallback', 'POST/authenticate',
-        'GET/installer/prerequisites', 'GET/installer/databaseConnection', 'GET/installer/sqlDataFiles', 'GET/installer/docservers', 'GET/installer/custom',
-        'POST/installer/custom', 'POST/installer/database', 'POST/installer/docservers', 'POST/installer/customization',
-        'PUT/installer/administrator', 'DELETE/installer/lock',
-        'GET/wopi/files/{id}', 'GET/wopi/files/{id}/contents', 'POST/wopi/files/{id}/contents','GET/onlyOffice/content','GET/languages/{lang}',
+        'GET/wopi/files/{id}', 'GET/wopi/files/{id}/contents', 'POST/wopi/files/{id}/contents','GET/onlyOffice/content','GET/languages/{lang}'
     ];
 
     public function getInformations(Request $request, Response $response)
@@ -715,4 +712,21 @@ class AuthenticationController
 
         return true;
     }
+
+    public static function canAccessInstallerWhitoutAuthentication(array $args)
+    {
+        $installerRoutes = [
+            'GET/installer/prerequisites', 'GET/installer/databaseConnection', 'GET/installer/sqlDataFiles', 'GET/installer/docservers', 'GET/installer/custom',
+            'GET/installer/customs', 'POST/installer/custom', 'POST/installer/database', 'POST/installer/docservers', 'POST/installer/customization',
+            'PUT/installer/administrator', 'DELETE/installer/lock'
+        ];
+
+        if (is_file("custom/custom.json")) {
+            return false;
+        } elseif (!in_array($args['route'], $installerRoutes)) {
+            return false;
+        }
+
+        return true;
+    }
 }
diff --git a/src/core/controllers/InstallerController.php b/src/core/controllers/InstallerController.php
index 4430f8f84dabc80c3b027fc86331abe6fd4bed38..d2dc17ee9f1d537d8b8b6105b5e45c48362d2bb9 100644
--- a/src/core/controllers/InstallerController.php
+++ b/src/core/controllers/InstallerController.php
@@ -14,9 +14,11 @@
 
 namespace SrcCore\controllers;
 
+use Group\controllers\PrivilegeController;
 use Respect\Validation\Validator;
 use Slim\Http\Request;
 use Slim\Http\Response;
+use SrcCore\models\AuthenticationModel;
 use SrcCore\models\CoreConfigModel;
 use SrcCore\models\DatabaseModel;
 use SrcCore\models\DatabasePDO;
@@ -26,6 +28,10 @@ class InstallerController
 {
     public function getPrerequisites(Request $request, Response $response)
     {
+        if (!empty($GLOBALS['id']) && !PrivilegeController::hasPrivilege(['privilegeId' => 'create_custom', 'userId' => $GLOBALS['id']])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Route forbidden']);
+        }
+
         $phpVersion = phpversion();
         $phpVersionValid = (version_compare(PHP_VERSION, '7.2') >= 0);
 
@@ -89,6 +95,10 @@ class InstallerController
 
     public function checkDatabaseConnection(Request $request, Response $response)
     {
+        if (!empty($GLOBALS['id']) && !PrivilegeController::hasPrivilege(['privilegeId' => 'create_custom', 'userId' => $GLOBALS['id']])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Route forbidden']);
+        }
+
         $queryParams = $request->getQueryParams();
 
         if (!Validator::stringType()->notEmpty()->validate($queryParams['server'])) {
@@ -140,6 +150,10 @@ class InstallerController
 
     public function getSQLDataFiles(Request $request, Response $response)
     {
+        if (!empty($GLOBALS['id']) && !PrivilegeController::hasPrivilege(['privilegeId' => 'create_custom', 'userId' => $GLOBALS['id']])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Route forbidden']);
+        }
+
         $dataFiles = [];
 
         $sqlFiles =  scandir('sql');
@@ -157,6 +171,10 @@ class InstallerController
 
     public function checkDocservers(Request $request, Response $response)
     {
+        if (!empty($GLOBALS['id']) && !PrivilegeController::hasPrivilege(['privilegeId' => 'create_custom', 'userId' => $GLOBALS['id']])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Route forbidden']);
+        }
+
         $queryParams = $request->getQueryParams();
 
         if (!Validator::stringType()->notEmpty()->validate($queryParams['path'])) {
@@ -190,6 +208,10 @@ class InstallerController
 
     public function checkCustomName(Request $request, Response $response)
     {
+        if (!empty($GLOBALS['id']) && !PrivilegeController::hasPrivilege(['privilegeId' => 'create_custom', 'userId' => $GLOBALS['id']])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Route forbidden']);
+        }
+
         $queryParams = $request->getQueryParams();
 
         if (!Validator::stringType()->notEmpty()->validate($queryParams['customId'])) {
@@ -214,8 +236,46 @@ class InstallerController
         return $response->withStatus(204);
     }
 
+    public function getCustoms(Request $request, Response $response)
+    {
+        if (!empty($GLOBALS['id']) && !PrivilegeController::hasPrivilege(['privilegeId' => 'create_custom', 'userId' => $GLOBALS['id']])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Route forbidden']);
+        }
+
+        if (!is_dir('custom')) {
+            return $response->withJson(['customs' => []]);
+        }
+
+        $customs = [];
+        $customsDirectories = scandir('custom');
+        foreach ($customsDirectories as $custom) {
+            if (in_array($custom, ['custom.json', '.', '..'])) {
+                continue;
+            }
+
+            $path = "custom/{$custom}/apps/maarch_entreprise/xml/config.json";
+            if (!file_exists($path)) {
+                continue;
+            }
+
+            $file = file_get_contents($path);
+            $file = json_decode($file, true);
+
+            $customs[] = [
+                'id'    => $custom,
+                'label' => $file['config']['applicationName']
+            ];
+        }
+
+        return $response->withJson(['customs' => $customs]);
+    }
+
     public function createCustom(Request $request, Response $response)
     {
+        if (!empty($GLOBALS['id']) && !PrivilegeController::hasPrivilege(['privilegeId' => 'create_custom', 'userId' => $GLOBALS['id']])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Route forbidden']);
+        }
+
         $body = $request->getParsedBody();
 
         if (!Validator::stringType()->notEmpty()->validate($body['customId'])) {
@@ -272,6 +332,10 @@ class InstallerController
 
     public function createDatabase(Request $request, Response $response)
     {
+        if (!empty($GLOBALS['id']) && !PrivilegeController::hasPrivilege(['privilegeId' => 'create_custom', 'userId' => $GLOBALS['id']])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Route forbidden']);
+        }
+
         $body = $request->getParsedBody();
 
         if (!Validator::stringType()->notEmpty()->validate($body['server'])) {
@@ -369,6 +433,10 @@ class InstallerController
 
     public function createDocservers(Request $request, Response $response)
     {
+        if (!empty($GLOBALS['id']) && !PrivilegeController::hasPrivilege(['privilegeId' => 'create_custom', 'userId' => $GLOBALS['id']])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Route forbidden']);
+        }
+
         $body = $request->getParsedBody();
 
         if (!Validator::stringType()->notEmpty()->validate($body['path'])) {
@@ -450,6 +518,10 @@ class InstallerController
 
     public function createCustomization(Request $request, Response $response)
     {
+        if (!empty($GLOBALS['id']) && !PrivilegeController::hasPrivilege(['privilegeId' => 'create_custom', 'userId' => $GLOBALS['id']])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Route forbidden']);
+        }
+
         $body = $request->getParsedBody();
 
         if (!Validator::stringType()->notEmpty()->validate($body['bodyLoginBackground'])) {
@@ -523,6 +595,10 @@ class InstallerController
 
     public function updateAdministrator(Request $request, Response $response)
     {
+        if (!empty($GLOBALS['id']) && !PrivilegeController::hasPrivilege(['privilegeId' => 'create_custom', 'userId' => $GLOBALS['id']])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Route forbidden']);
+        }
+
         $body = $request->getParsedBody();
 
         if (!Validator::stringType()->notEmpty()->validate($body['customId'])) {
@@ -546,28 +622,37 @@ class InstallerController
         DatabasePDO::reset();
         new DatabasePDO(['customId' => $body['customId']]);
 
-        $userAlreadyExists = UserModel::getByLogin(['login' => strtolower($body['login']), 'select' => [1]]);
-        if (!empty($userAlreadyExists)) {
-            return $response->withStatus(400)->withJson(['errors' => 'User already exists', 'lang' => 'alreadyExist']);
+        $body['login'] = strtolower($body['login']);
+        $user = UserModel::getByLogin(['login' => $body['login'], 'select' => ['id']]);
+
+        if (!empty($user)) {
+            UserModel::update([
+                'set'   => [
+                    'firstname'     => $body['firstname'],
+                    'lastname'      => $body['lastname'],
+                    'mail'          => $body['email'],
+                    'password'      => AuthenticationModel::getPasswordHash($body['password']),
+                    'mode'          => 'root_invisible'
+                ],
+                'where' => ['id = ?'],
+                'data'  => [$user['id']]
+            ]);
+        } else {
+            UserModel::create([
+                'user' => [
+                    'userId'        => $body['login'],
+                    'firstname'     => $body['firstname'],
+                    'lastname'      => $body['lastname'],
+                    'mail'          => $body['email'],
+                    'preferences'   => json_encode(['documentEdition' => 'java']),
+                    'password'      => $body['password'],
+                    'mode'          => 'root_invisible'
+                ]
+            ]);
         }
 
-        UserModel::create([
-            'user' => [
-                'userId'        => $body['login'],
-                'firstname'     => $body['firstname'],
-                'lastname'      => $body['lastname'],
-                'mail'          => $body['email'],
-                'preferences'   => json_encode(['documentEdition' => 'java']),
-                'password'      => $body['password'],
-                'mode'          => 'root_invisible'
-            ]
-        ]);
-
-        DatabaseModel::update([
-            'table'     => 'users',
-            'set'       => [
-                'mail'      => $body['email']
-            ],
+        UserModel::update([
+            'set'       => ['mail' => $body['email']],
             'where'     => ['mail = ?'],
             'data'      => ['support@maarch.fr']
         ]);
@@ -577,6 +662,10 @@ class InstallerController
 
     public function terminateInstaller(Request $request, Response $response)
     {
+        if (!empty($GLOBALS['id']) && !PrivilegeController::hasPrivilege(['privilegeId' => 'create_custom', 'userId' => $GLOBALS['id']])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Route forbidden']);
+        }
+
         $body = $request->getParsedBody();
 
         if (!Validator::stringType()->notEmpty()->validate($body['customId'])) {