diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..b031331fe0b9705c699fc22dd044f867c1fb1505
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,2 @@
+src/
+ldap_connexion_config.json
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9386d1b1379ce418459cd00beec21ecc43d3a7bd..77a886f18139a4fc9c53de74056d2dbf610190ae 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,6 +1,6 @@
 # Official framework image. Look for the different tagged releases at:
 # https://hub.docker.com/r/library/node/tags/
-image: node:latest
+image: node:10-slim
 
 # Only needed when using a docker container to run your tests in.
 # Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
@@ -25,8 +25,6 @@ stages:
 # make migrations on and seed the db
 install-dependencies:
   stage: install
-  before_script: 
-    - npm i -g npm
   script:
     - npm ci
   artifacts:
diff --git a/Dockerfile b/Dockerfile
index 2a69b6ceb89e2e234c8dd76d900649c4a856d1dd..6efd65c661ade15fd90973b4884f3a12f0368a0d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,3 +1,3 @@
 FROM node:10.9-alpine
 
-RUN npm install
+CMD [ "node", "build/bundle.js" ]
diff --git a/README.md b/README.md
index 91ffe8519a593e3a288bf31b1cf7faf082b39e68..d41a124426bb148a0fddfeb4b55fa8939d6cd775 100644
--- a/README.md
+++ b/README.md
@@ -41,6 +41,7 @@ L'API de Sigma nécessite de se connecter au LDAP Frankiz, à la fois pour obten
 
 * La configuration LDAP de base se situe dans [ldap_config.json](ldap_config.json).
 * Elle est importée dans l'application depuis [src/ldap/config.js](src/ldap/config.js). Ce fichier écrase la config de base selon les options suivantes :
+
     | **Variable** | **Description** | **Défaut** (`ldap_config.json`) |
     | ------ | ------ | ----- |
     | LDAP_URI | URI vers le serveur LDAP. | <ldap://frankiz.eleves.polytechnique.fr:389> |
diff --git a/package-lock.json b/package-lock.json
index 75e5fa9b5c291c5a746d1eb0ae0480326a05f9d8..fcc43b467a3c99c80f78ed0f383fa3a95a3d8035 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -201,6 +201,23 @@
         "@types/node": "*"
       }
     },
+    "@types/connect-ensure-login": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/@types/connect-ensure-login/-/connect-ensure-login-0.1.4.tgz",
+      "integrity": "sha512-MLXOS6+5MnhkB7F34xE66wX9MEEfrUJRfNM9Uv0vEre8kH13tILO9j2b7fI4xwyLXSEn9k3uIE8U46MQ1CWByw==",
+      "dev": true,
+      "requires": {
+        "@types/express": "*"
+      }
+    },
+    "@types/connect-flash": {
+      "version": "0.0.34",
+      "resolved": "https://registry.npmjs.org/@types/connect-flash/-/connect-flash-0.0.34.tgz",
+      "integrity": "sha512-QC93TwnTZ0sk//bfT81o7U4GOedbOZAcgvqi0v1vJqCESC8tqIVnhzB1CHiAUBUWFjoxG5JQF0TYaNa6DMb6Ig==",
+      "requires": {
+        "@types/express": "*"
+      }
+    },
     "@types/events": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
@@ -245,14 +262,15 @@
       "integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA=="
     },
     "@types/node": {
-      "version": "9.4.7",
-      "resolved": "http://registry.npmjs.org/@types/node/-/node-9.4.7.tgz",
-      "integrity": "sha512-4Ba90mWNx8ddbafuyGGwjkZMigi+AWfYLSDCpovwsE63ia8w93r3oJ8PIAQc3y8U+XHcnMOHPIzNe3o438Ywcw=="
+      "version": "10.9.3",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-10.9.3.tgz",
+      "integrity": "sha512-DOzWZKUnmFYG0KUOs+9HEBju2QhBU6oM2zeluunQNt0vnJvnkHvtDNlQPZDkTrkC5pZrNx1TPqeL137zciXZMQ=="
     },
     "@types/passport": {
-      "version": "0.3.5",
-      "resolved": "https://registry.npmjs.org/@types/passport/-/passport-0.3.5.tgz",
-      "integrity": "sha512-J7mdY1nnhjdbkXT84S3WsyrTtDf2KqUJ9JW3Y9vxA5GuXlejIuvwHw9A2TdNklAqPG2Q0TWqlsA2a2GIeV1jYA==",
+      "version": "0.4.6",
+      "resolved": "https://registry.npmjs.org/@types/passport/-/passport-0.4.6.tgz",
+      "integrity": "sha512-P7TxrdpAze3nvHghYPeLlHkYcFDiIkRBbp7xYz2ehX9zmi1yr/qWQMTpXsMxN5w3ESJpMzn917inK4giASaDcQ==",
+      "dev": true,
       "requires": {
         "@types/express": "*"
       }
@@ -4168,14 +4186,12 @@
         "balanced-match": {
           "version": "1.0.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "brace-expansion": {
           "version": "1.1.11",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "balanced-match": "^1.0.0",
             "concat-map": "0.0.1"
@@ -4190,20 +4206,17 @@
         "code-point-at": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "concat-map": {
           "version": "0.0.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "console-control-strings": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "core-util-is": {
           "version": "1.0.2",
@@ -4320,8 +4333,7 @@
         "inherits": {
           "version": "2.0.3",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "ini": {
           "version": "1.3.5",
@@ -4333,7 +4345,6 @@
           "version": "1.0.0",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "number-is-nan": "^1.0.0"
           }
@@ -4348,7 +4359,6 @@
           "version": "3.0.4",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "brace-expansion": "^1.1.7"
           }
@@ -4356,14 +4366,12 @@
         "minimist": {
           "version": "0.0.8",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "minipass": {
           "version": "2.2.4",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "safe-buffer": "^5.1.1",
             "yallist": "^3.0.0"
@@ -4382,7 +4390,6 @@
           "version": "0.5.1",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "minimist": "0.0.8"
           }
@@ -4463,8 +4470,7 @@
         "number-is-nan": {
           "version": "1.0.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "object-assign": {
           "version": "4.1.1",
@@ -4476,7 +4482,6 @@
           "version": "1.4.0",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "wrappy": "1"
           }
@@ -4598,7 +4603,6 @@
           "version": "1.0.2",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "code-point-at": "^1.0.0",
             "is-fullwidth-code-point": "^1.0.0",
@@ -7736,6 +7740,14 @@
           "version": "7.0.56",
           "resolved": "http://registry.npmjs.org/@types/node/-/node-7.0.56.tgz",
           "integrity": "sha512-NgjN3xPyqbAXSIpznNAR5Cisx5uKqJWxcS9kefzSFEX/9J7O01/FHyfnvPI7SztBf9p6c8mqOn3olZWJx3ja6g=="
+        },
+        "@types/passport": {
+          "version": "0.3.5",
+          "resolved": "https://registry.npmjs.org/@types/passport/-/passport-0.3.5.tgz",
+          "integrity": "sha512-J7mdY1nnhjdbkXT84S3WsyrTtDf2KqUJ9JW3Y9vxA5GuXlejIuvwHw9A2TdNklAqPG2Q0TWqlsA2a2GIeV1jYA==",
+          "requires": {
+            "@types/express": "*"
+          }
         }
       }
     },
@@ -9715,6 +9727,19 @@
       "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
       "dev": true
     },
+    "ts-loader": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-4.5.0.tgz",
+      "integrity": "sha512-ihgVaSmgrX4crGV4n7yuoHPoCHbDzj9aepCZR9TgIx4SgJ9gdnB6xLHgUBb7bsFM/f0K6x9iXa65KY/Fu1Klkw==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.3.0",
+        "enhanced-resolve": "^4.0.0",
+        "loader-utils": "^1.0.2",
+        "micromatch": "^3.1.4",
+        "semver": "^5.0.1"
+      }
+    },
     "tslib": {
       "version": "1.9.3",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
@@ -9750,6 +9775,12 @@
       "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
       "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
     },
+    "typescript": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.3.tgz",
+      "integrity": "sha512-kk80vLW9iGtjMnIv11qyxLqZm20UklzuR2tL0QAnDIygIUIemcZMxlMWudl9OOt76H3ntVzcTiddQ1/pAAJMYg==",
+      "dev": true
+    },
     "uglify-js": {
       "version": "2.8.29",
       "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
diff --git a/package.json b/package.json
index bdd1bb6689c5ab89ae85bc9274d41c810e56de20..6d5a9fd574bec411594f6e88adf9576c5f38ea4f 100644
--- a/package.json
+++ b/package.json
@@ -48,6 +48,10 @@
     "url-loader": "^0.6.2"
   },
   "devDependencies": {
+    "@types/connect-ensure-login": "^0.1.4",
+    "@types/connect-flash": "0.0.34",
+    "@types/node": "^10.9.3",
+    "@types/passport": "^0.4.6",
     "babel-eslint": "^8.2.6",
     "eslint": "^4.19.1",
     "eslint-config-standard": "^11.0.0",
@@ -58,6 +62,8 @@
     "eslint-plugin-standard": "^3.1.0",
     "jsdoc": "^3.5.5",
     "nodemon": "^1.18.3",
+    "ts-loader": "^4.5.0",
+    "typescript": "^3.0.3",
     "webpack": "^4.17.1",
     "webpack-cli": "^2.1.5",
     "webpack-node-externals": "^1.7.2"
diff --git a/src/admin_view/admin.router.js b/src/admin_view/admin.router.ts
similarity index 95%
rename from src/admin_view/admin.router.js
rename to src/admin_view/admin.router.ts
index a7b8b2a4056a66bb209c1f155ffe706072b774a7..a3c0f7f75deef6a2d8781aabd4bfb7f35591dae6 100644
--- a/src/admin_view/admin.router.js
+++ b/src/admin_view/admin.router.ts
@@ -10,10 +10,13 @@
 import { Router } from 'express';
 import knex from '../../db/knex_router';
 import passport from 'passport';
+import flash from 'connect-flash';
 import { ensureLoggedIn } from 'connect-ensure-login';
 
 const router = Router();
 
+router.use(flash());
+
 let port = process.env.PORT || 3000;
 
 
@@ -23,9 +26,6 @@ let port = process.env.PORT || 3000;
  */
 
 router.get('/', function (req, res) {
-    console.log("adminview: GET handler for /adminview route");
-    console.log('adminview: Connecting to ' + req.url);
-    console.log('adminview: Trying to go to admin page...');
     res.redirect('/adminview/admin');
 });
 
@@ -47,7 +47,6 @@ router.get('/admin',
         // donc on laisse passer sans déclencher d'erreur 500
         try {
             let user = req.user;
-            //let user = req.user;
             console.log('adminview: Welcome,', user.uid);
             userName = user.uid;
         } catch (err) {
diff --git a/src/config_passport.js b/src/config_passport.js
index f07fa2fe73a935c58ebc064721536dcf3f5bd91b..ca35df95e59b4e8b9b87e5a4937b5bd1794c1d82 100644
--- a/src/config_passport.js
+++ b/src/config_passport.js
@@ -17,18 +17,16 @@
 */
 import passport from 'passport';
 import LdapStrategy from 'passport-ldapauth';
-import fs from 'fs';
-import path from 'path';
-import { config } from './ldap/config';
+import { ldapConfig } from './ldap/config';
 
 // specifies options for 'ldapauth' strategy, to customize the behaviour of subsequent passport.authenticate('ldapauth') calls
 passport.use(new LdapStrategy({
     server: {
-        url: config.ldap.server,
+        url: ldapConfig.ldap.server,
         //bindDn: '.............',
         //bindCredentials: '..........',
-        searchBase: config.ldap.searchBase,
-        searchFilter: config.ldap.searchFilter,
+        searchBase: ldapConfig.ldap.searchBase,
+        searchFilter: ldapConfig.ldap.searchFilter,
         //searchAttributes: ['givenName', 'sn'],
         //tlsOptions: '..........',
     },
diff --git a/src/index.js b/src/index.js
deleted file mode 100644
index d7929d9739ea580e9c23d5eb61d7231ce4b1e46b..0000000000000000000000000000000000000000
--- a/src/index.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * @file Lance le serveur configuré dans {@link server.js}
- * @author manifold
- */
-import app from './server';
-import colors from 'colors';
-import passport from 'passport';
-
-const port = process.env.PORT || 3000;
-
-app.listen(port, () => {
-    console.log(colors.blue(`Express server listening on port ${port}.`));
-});
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4773230279d6960d6e51d06fb1393dc061c8191f
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,12 @@
+/**
+ * @file Lance le serveur configuré dans {@link server.ts}
+ * @author manifold
+ */
+import app from './server';
+import colors from 'colors';
+
+const port = process.env.PORT || 3000;
+
+app.listen(port, () => {
+    console.log(colors.blue("Express server listening on port %s."), port);
+});
diff --git a/src/ldap/config.js b/src/ldap/config.js
index 1c4793a8408e4e9cb187230db6fb3eb1be92bfcc..91d253a311ebee5f62bfcbde998096d0d4db7be6 100644
--- a/src/ldap/config.js
+++ b/src/ldap/config.js
@@ -2,18 +2,23 @@
  * @file Importe la configuration du LDAP au sein de l'application, et remplace certaines valeurs en fonction des variables d'environnement.
  * @author manifold
  */
-var fs = require('fs');
-var path = require('path');
-
+const fs = require('fs');
+const path = require('path');
+const colors = require('colors');
 // Point central ; tous les champs de la BDD sont 'cachés' dans config.json et pas visibles directement
-var configPath = path.resolve('./', 'ldap_config.json');
-const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
+const configPath = path.resolve('./', 'ldap_config.json');
+const credsPath = path.resolve('./', 'ldap_connexion_config.json');
+console.log(colors.cyan("Loading LDAP config file from %s"), configPath);
+console.log(colors.cyan("Loading LDAP credentials from %s"), credsPath);
+const ldapConfig = JSON.parse(fs.readFileSync(configPath));
+const credentialsConfig = JSON.parse(fs.readFileSync(credsPath));
 
 // Override config server from environment
 if (process.env.LDAP_URI != null) {
-    config.ldap.server = process.env.LDAP_URI;
+    ldapConfig.ldap.server = process.env.LDAP_URI;
 }
 
 module.exports = {
-    config
+    ldapConfig,
+    credentialsConfig
 };
diff --git a/src/ldap/ldap_data.js b/src/ldap/ldap_data.js
index c7c298a2e3aebc158ec148c799b8c2d1200da133..24407ef0e025c6a534826103fb48fcf591d98712 100644
--- a/src/ldap/ldap_data.js
+++ b/src/ldap/ldap_data.js
@@ -22,10 +22,10 @@ var path = require('path');
 // Important ; permet de vérifier que l'utilisateur reste connecté.
 var ensureLoggedin =  require('connect-ensure-login').ensureLoggedIn;
 
-const config = require('./config').config;
+const { ldapConfig, credentialsConfig } = require('./config');
 // Connection au serveur LDAP avec des temps de timeout arbitraires
-var client = ldap.createClient({url: config.ldap.server});
-console.log(`Connecting to LDAP at ${config.ldap.server}.`);
+var client = ldap.createClient({url: ldapConfig.ldap.server});
+console.log(`Connecting to LDAP at ${ldapConfig.ldap.server}.`);
 
 //------------------------------------------------------------------------------------------------------------------------
 // Fonctions de base
@@ -138,7 +138,7 @@ function ajouterLDAP(user, dn, vals) {
     return new Promise((resolve, reject) => {
         connecterLDAP(user);
         // Ajout LDAP selon la configuration en argument
-        client.add(config.key_id+"="+vals[config.key_id]+","+dn, vals, function(err) {
+        client.add(ldapConfig.key_id+"="+vals[ldapConfig.key_id]+","+dn, vals, function(err) {
             reject(err);
         });
         client.bind("", "", (err, res) => {});
@@ -192,13 +192,13 @@ function trouverGroupesModulable(input, return_attributes) {
         let str=ldapEscape.filter("${txt}", { txt: input});
 
         // Construction du filtre custom
-        let filter= "(|("+config.key_id+"="+str+")"+      // On cherche la valeur exacte
-                    "(|("+config.key_id+"=*"+str+")"+     // La valeur finale avec des trucs avant ; wildcard *
-                    "(|("+config.key_id+"=*"+str+"*)"+    // La valeur du milieu avec des trucs avant et après
-                    "("+config.key_id+"="+str+"*))))";   // La valeur du début avec des trucs après
+        let filter= "(|("+ldapConfig.key_id+"="+str+")"+      // On cherche la valeur exacte
+                    "(|("+ldapConfig.key_id+"=*"+str+")"+     // La valeur finale avec des trucs avant ; wildcard *
+                    "(|("+ldapConfig.key_id+"=*"+str+"*)"+    // La valeur du milieu avec des trucs avant et après
+                    "("+ldapConfig.key_id+"="+str+"*))))";   // La valeur du début avec des trucs après
 
         // Appel rechercheLDAP avec filtre de l'espace 
-        rechercherLDAP(config.dn_groups, return_attributes, filter).then(res => resolve(res));
+        rechercherLDAP(ldapConfig.dn_groups, return_attributes, filter).then(res => resolve(res));
     });
 }
 
@@ -237,7 +237,7 @@ function repliquerTOLModulable(data, return_attributes) {
                     // Escape de l'input utilisateur
                     let str=ldapEscape.filter("${input}", { input: val});
                     // Traduction en language LDAP
-                    let attribute = config.user[key];
+                    let attribute = ldapConfig.user[key];
                     // Creation du filtre étape par étape
                     filter="(&"+filter+ "(|("+attribute+"="+str+")"+      // On cherche la valeur exacte
                                         "(|("+attribute+"=*"+str+")"+     // La valeur finale avec des trucs avant ; wildcard * (MEF la wildcart ne marche pas pour tous les attributs)
@@ -247,7 +247,7 @@ function repliquerTOLModulable(data, return_attributes) {
             }
         }
         // Appel rechercheLDAP avec filtre de l'espace 
-        rechercherLDAP(config.dn_users, return_attributes, filter).then(res => resolve(res));
+        rechercherLDAP(ldapConfig.dn_users, return_attributes, filter).then(res => resolve(res));
     });
 }
 
@@ -260,7 +260,7 @@ function repliquerTOLModulable(data, return_attributes) {
  * @return {Promise(Object[])} Liste de dictionnaires de profils en cohérence avec l'input avec pour clés tous les attributs disponibles ou presque (voir config).
  */
 function repliquerTOL(data) {
-    return repliquerTOLModulable(data, config.user.profil);
+    return repliquerTOLModulable(data, ldapConfig.user.profil);
 }
 
 /**
@@ -279,7 +279,7 @@ function repliquerTOL(data) {
 function assurerUnicite(valeur, attribut, dn, evoluerValeur, n=0) {
     return new Promise((resolve, reject) => { 
         // Recherche d'autres occurences de l'id
-        rechercherLDAP(dn, config.key_id, "("+attribut+"="+valeur+")").then(matches => {
+        rechercherLDAP(dn, ldapConfig.key_id, "("+attribut+"="+valeur+")").then(matches => {
             // On renvoit la valeur si elle est bien unique
             if (matches.length==0) { resolve(valeur); }
             // Sinon, on tente de nouveau notre chance avec la valeur suivante
@@ -299,7 +299,7 @@ function assurerUnicite(valeur, attribut, dn, evoluerValeur, n=0) {
 function genererUid(givenName, lastName, promotion) {
     // Le filtrage évite l'injection de code dans le LDAP, le normalize et lowerCase standardisent le format
     return new Promise((resolve, reject) => {
-        assurerUnicite(ldapEscape.filter("${uid}",{uid: givenName+'.'+lastName}).toLowerCase().normalize('UFD'), config.key_id, config.dn_users, (id,n) => {
+        assurerUnicite(ldapEscape.filter("${uid}",{uid: givenName+'.'+lastName}).toLowerCase().normalize('UFD'), ldapConfig.key_id, ldapConfig.dn_users, (id,n) => {
             if (n==1) { id+='.'+ldapEscape.filter("${pr}",{pr: promotion}); }   // Si prénom.nom existe déjà, on rajoute la promo
             else if (n==2) { id+='.'+n-1; }                                     // Puis si prénom.nom.promo existe déjà on passe à nom.prenom.promo .1
             else if (n>2) { id+=+n; }                                           // Ensuite on continue .23, .234, etc...
@@ -317,7 +317,7 @@ function genererUid(givenName, lastName, promotion) {
 function genererGid(name) {
     // Le filtrage évite l'injection de code dans le LDAP, le normalize et lowerCase standardisent le format
     return new Promise((resolve, reject) => {
-        assurerUnicite(ldapEscape.filter("${id}",{id: name}).toLowerCase().normalize('UFD'), config.key_id, config.dn_groups, (id,n) => {
+        assurerUnicite(ldapEscape.filter("${id}",{id: name}).toLowerCase().normalize('UFD'), ldapConfig.key_id, ldapConfig.dn_groups, (id,n) => {
             if (n==1) { id+='.'+n; }    // Si nom existe déjà, on essaie nom.1
             else if (n>1) { id+=+n; }   // Ensuite on continue .12, .123, etc...
             return id;
@@ -395,9 +395,9 @@ class UtilisateurAnonyme {
      * @return {Promise(string[])} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre
      */
     listGroups(uid) {
-        let filtered_request = ldapEscape.filter(config.key_id + "=${id}," + config.dn_users, { id: uid });
+        let filtered_request = ldapEscape.filter(ldapConfig.key_id + "=${id}," + ldapConfig.dn_users, { id: uid });
         // console.log(filtered_request);
-        return rechercherLDAP(filtered_request, config.user.groups)
+        return rechercherLDAP(filtered_request, ldapConfig.user.groups)
             .then(res => res[0]);
     }
     
@@ -408,9 +408,9 @@ class UtilisateurAnonyme {
      * @return {Promise(String[])} Liste des uid des membres où l'id fournie est membre (noms flat des groupes)
      */
     listMembers(uid) {
-        let filtered_request = ldapEscape.filter(config.key_id + "=${id}," + config.dn_groups, { id: uid });
+        let filtered_request = ldapEscape.filter(ldapConfig.key_id + "=${id}," + ldapConfig.dn_groups, { id: uid });
         // console.log(filtered_request);
-        return rechercherLDAP(filtered_request, config.group.member)
+        return rechercherLDAP(filtered_request, ldapConfig.group.member)
             .then(res => res);
     }
     
@@ -423,7 +423,7 @@ class UtilisateurAnonyme {
     listAdmins(gid) {
         return new Promise((resolve, reject) => {
             rechercherLDAP(ldapEscape.filter(
-                config.key_id+"=${id},"+config.dn_users, {id : gid}), config.group.admin).then(res => resolve(res[0])
+                ldapConfig.key_id+"=${id},"+ldapConfig.dn_users, {id : gid}), ldapConfig.group.admin).then(res => resolve(res[0])
             );
         });
     }
@@ -436,7 +436,7 @@ class UtilisateurAnonyme {
      * voir `ldap_config.json`(..\..\ldap_config.json) pour les clés exactes.
      */
     getUser(uid) {
-        return rechercherLDAP(ldapEscape.filter(config.key_id+"=${id},"+config.dn_users, {id : uid}), config.user.profil);
+        return rechercherLDAP(ldapEscape.filter(ldapConfig.key_id+"=${id},"+ldapConfig.dn_users, {id : uid}), ldapConfig.user.profil);
     }
      
     /**
@@ -447,9 +447,9 @@ class UtilisateurAnonyme {
      * voir `ldap_config.json`(../../ldap_config.json) pour les clés exactes.
      */
     getGroup(gid) {
-        let filtered_request = ldapEscape.filter(config.key_id + "=${id}," + config.dn_groups, { id: gid });
+        let filtered_request = ldapEscape.filter(ldapConfig.key_id + "=${id}," + ldapConfig.dn_groups, { id: gid });
         // console.log(filtered_request);
-        return rechercherLDAP(filtered_request, config.group.profil);
+        return rechercherLDAP(filtered_request, ldapConfig.group.profil);
     }
 
     //------------------------------------------------------------------------------------------------------------------------
@@ -466,11 +466,11 @@ class UtilisateurAnonyme {
     trouverGroupesParTypes(input, type) {
         return new Promise((resolve, reject) => {
             // Simple appel à la fonction précédente
-            trouverGroupesModulable(input, [config.key_id, config.group.type]).then(gList => {
+            trouverGroupesModulable(input, [ldapConfig.key_id, ldapConfig.group.type]).then(gList => {
                 let gidtyList = [];
                 gList.forEach(g => {
                     // Si le groupe est du bon type on rajoute son gid
-                    if (g[config.group.type]==type) { gidtyList.push(g[config.key_id]); }
+                    if (g[ldapConfig.group.type]==type) { gidtyList.push(g[ldapConfig.key_id]); }
                 });
                 resolve(gidtyList);
             });
@@ -486,7 +486,7 @@ class UtilisateurAnonyme {
      */
     repliquerTOLdesIds(data) {
         return new Promise((resolve, reject) => {
-            repliquerTOLModulable(data, config.key_id).then(res => {
+            repliquerTOLModulable(data, ldapConfig.key_id).then(res => {
                 resolve(res);
             });
         });
@@ -529,56 +529,56 @@ class UtilisateurConnecte extends UtilisateurAnonyme {
             let vals = {};
     
             // uid de base généré à partir du nom standardisé
-            genererGid(user, data['name']).then(id => { vals[config.group['name']]=id; });
+            genererGid(user, data['name']).then(id => { vals[ldapConfig.group['name']]=id; });
     
             // Ecriture de toutes les valeurs directement inscrites dans le LDAP (in pour input)
-            config.group.direct_input.forEach(key_att => vals[config.group[key_att]]=data[key_att]);
+            ldapConfig.group.direct_input.forEach(key_att => vals[ldapConfig.group[key_att]]=data[key_att]);
     
             // Appel à la fonction de base
-            ajouterLDAP(user, config.key_id+"="+vals[config.group['name']]+","+config.dn_groups, vals).then( res => {
+            ajouterLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.group['name']]+","+ldapConfig.dn_groups, vals).then( res => {
                 // Certains champs nécessitent de petits calculs
                 let vals2={};
     
                 // Sauvegarde du nom (pour le cas où gid != data['name'])
-                vals2[config.group["name"]]=data['name'];
+                vals2[ldapConfig.group["name"]]=data['name'];
     
                 // ?!
-                vals2[config.user['password']] =  '';
+                vals2[ldapConfig.user['password']] =  '';
     
                 // Génération id aléatoire et test contre le LDAP
-                genererIdNum(user, config.groups["idNumber"], config.dn_groups).then(id => { vals2[config.group['idNumber']]=id; });
+                genererIdNum(user, ldapConfig.groups["idNumber"], ldapConfig.dn_groups).then(id => { vals2[ldapConfig.group['idNumber']]=id; });
                 // FOIREUX : Hypothèse sur la structure du reste des données mais évite un assurerUnicite à deux variables
-                vals2[config.group['idNumber2']]=vals2[config.group['idNumber']];
+                vals2[ldapConfig.group['idNumber2']]=vals2[ldapConfig.group['idNumber']];
                 
                 // Stockage machine ; dépend du prénom
-                vals2[config.group['directory']] = '/hosting/groups/'+vals[config.key_id];
+                vals2[ldapConfig.group['directory']] = '/hosting/groups/'+vals[ldapConfig.key_id];
     
                 // Code root
-                vals2[config.group['cleanFullName']]=data['name'].replace(':', ';').toLowerCase().normalize('UFD');
+                vals2[ldapConfig.group['cleanFullName']]=data['name'].replace(':', ';').toLowerCase().normalize('UFD');
                 
                 // Adressage root
-                vals2[config.group['login']] = "/sbin/nologin";
+                vals2[ldapConfig.group['login']] = "/sbin/nologin";
                 
                 // Permissions BR
-                vals2[config.group['readPerm']] = '!*';
-                vals2[config.group['writePerm']] = '!*';
+                vals2[ldapConfig.group['readPerm']] = '!*';
+                vals2[ldapConfig.group['writePerm']] = '!*';
     
                 // Inscription des valeurs calculées
-                modifierLDAP(user, config.key_id+"="+vals[config.key_id]+","+config.dn_groups, "add", vals2).then(res => {
+                modifierLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.key_id]+","+ldapConfig.dn_groups, "add", vals2).then(res => {
                     if (!res) { reject(false); }
                 });
     
                 ["posixAccount", "posixGroup", "brAccount"].forEach(cst => {
                     let vals3={};
-                    vals3[config.group['class']]=cst;
-                    modifierLDAP(user, config.key_id+"="+vals[config.key_id]+","+config.dn_groups, "add", vals3).then(res => {
+                    vals3[ldapConfig.group['class']]=cst;
+                    modifierLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.key_id]+","+ldapConfig.dn_groups, "add", vals3).then(res => {
                         if (!res) { reject(false); }
                     });
                 });
     
                 // Utilisation des fonctions adaptées pour assurer la cohérence de l'ensemble
-                data['members'].forEach(uid => { this.ajouterMembreGroupe(user, uid, vals[config.key_att]); });
-                data['admins'].forEach(uid => { this.ajouterAdministrateurGroupe(user, uid, vals[config.key_att]); });
+                data['members'].forEach(uid => { this.ajouterMembreGroupe(user, uid, vals[ldapConfig.key_att]); });
+                data['admins'].forEach(uid => { this.ajouterAdministrateurGroupe(user, uid, vals[ldapConfig.key_att]); });
     
                 resolve(true);
             });
@@ -607,8 +607,8 @@ class UtilisateurConnecte extends UtilisateurAnonyme {
             this.getUser(user, uid).then(profil => {
                 // Reecriture de profil avec les bons champs
                 Object.keys(profil).forEach(keyLDAP => {
-                    Object.keys(config.user).forEach(keyAlias => {
-                        config.user[keyAlias]=keyLDAP;
+                    Object.keys(ldapConfig.user).forEach(keyAlias => {
+                        ldapConfig.user[keyAlias]=keyLDAP;
                         profil[keyAlias]=profil[keyLDAP];
                     });
                 });
@@ -669,8 +669,8 @@ class AdministrateurConnecte extends UtilisateurConnecte {
             this.listMembers(user,gid).then(lm => {
                 if (!lm.includes(uid)) {
                     let vals = {};
-                    vals[config.groups.member] = uid;
-                    modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_groups, { id: gid }), "add", vals).then(res => {
+                    vals[ldapConfig.groups.member] = uid;
+                    modifierLDAP(user, ldapEscape(ldapConfig.key_id+"=${id},"+ldapConfig.dn_groups, { id: gid }), "add", vals).then(res => {
                         // Erreur si pb lors de la modification
                         if (!res) { reject(false); }
                     });
@@ -679,8 +679,8 @@ class AdministrateurConnecte extends UtilisateurConnecte {
             }).then(res => this.listGroups(user,uid)).then( lg => {
                 if (!lg.includes(gid)) {
                     let vals2 = {};
-                    vals2[config.users.groups] = gid;
-                    modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_users, { id: uid }), "add", vals2).then(res => {
+                    vals2[ldapConfig.users.groups] = gid;
+                    modifierLDAP(user, ldapEscape(ldapConfig.key_id+"=${id},"+ldapConfig.dn_users, { id: uid }), "add", vals2).then(res => {
                         // Erreur si pb lors de la modification
                         if (!res) { reject(false); }
                     });
@@ -704,7 +704,7 @@ class AdministrateurConnecte extends UtilisateurConnecte {
             this.listMembers(user,gid).then(lm => {
                 if (lm.includes(uid)) {
                     // Supprime tous les utilisateurs
-                    modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_groups, { id: gid }), "del", config.group.member).then(res => {
+                    modifierLDAP(user, ldapEscape(ldapConfig.key_id+"=${id},"+ldapConfig.dn_groups, { id: gid }), "del", ldapConfig.group.member).then(res => {
                         // Les rajoute un par un, sauf pour le supprimé
                         lm.forEach(id => {
                             if (id!=uid) { this.ajouterMembreGroupe(user,id, gid); }
@@ -715,7 +715,7 @@ class AdministrateurConnecte extends UtilisateurConnecte {
                 // Vérifie que l'utilisateur est pas déjà viré pour users
                 if (lg.includes(gid)) {
                     // Supprime tous les groupes
-                    modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_users, { id: uid }), "del", config.group.admin).then(res => {
+                    modifierLDAP(user, ldapEscape(ldapConfig.key_id+"=${id},"+ldapConfig.dn_users, { id: uid }), "del", ldapConfig.group.admin).then(res => {
                         // Les rajoute un par un, sauf pour le supprimé
                         lg.forEach(id => {
                             if (id!=gid) { this.ajouterMembreGroupe(user,uid, id); }
@@ -744,8 +744,8 @@ class AdministrateurConnecte extends UtilisateurConnecte {
                     if (!la.includes(uid)) {
                         // Finalement modification, uniquement dans groups
                         let vals = {};
-                        vals[config.groups.admin] = uid;
-                        modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_groups, { id: gid }), "add", vals).then(res => {
+                        vals[ldapConfig.groups.admin] = uid;
+                        modifierLDAP(user, ldapEscape(ldapConfig.key_id+"=${id},"+ldapConfig.dn_groups, { id: gid }), "add", vals).then(res => {
                             // Gestion d'erreur
                             if (!res) { reject(false); }
                         });
@@ -772,7 +772,7 @@ class AdministrateurConnecte extends UtilisateurConnecte {
             this.listAdmins(user,gid).then(la => {
                 if (la.includes(uid)) {
                     // Supprime tous les administrateurs
-                    modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_groups, { id: gid }), "del", config.group.admin).then(res => {
+                    modifierLDAP(user, ldapEscape(ldapConfig.key_id+"=${id},"+ldapConfig.dn_groups, { id: gid }), "del", ldapConfig.group.admin).then(res => {
                         // Les rajoute un par un, sauf pour le supprimé
                         la.forEach(id => {
                             if (id!=uid) { this.ajouterAdministrateurGroupe(user, id, gid); }
@@ -801,8 +801,8 @@ class AdministrateurConnecte extends UtilisateurConnecte {
             this.getGroup(user, gid).then(profil => {
                 // Reecriture de profil avec les bons champs
                 Object.keys(profil).forEach(keyLDAP => {
-                    Object.keys(config.group).forEach(keyAlias => {
-                        config.group[keyAlias]=keyLDAP;
+                    Object.keys(ldapConfig.group).forEach(keyAlias => {
+                        ldapConfig.group[keyAlias]=keyLDAP;
                         profil[keyAlias]=profil[keyLDAP];
                     });
                 });
@@ -835,11 +835,11 @@ class AdministrateurConnecte extends UtilisateurConnecte {
             // Gestion des membres et administrateurs d'abord
             this.getGroup(user, gid).then(profil => {
                 // Ordre important
-                profil[config.group['admin']].forEach(id => { this.removeGroupAdmin(user, id, gid); });
-                profil[config.group['member']].forEach(id => { this.removeGroupMember(user, id, gid); });
+                profil[ldapConfig.group['admin']].forEach(id => { this.removeGroupAdmin(user, id, gid); });
+                profil[ldapConfig.group['member']].forEach(id => { this.removeGroupMember(user, id, gid); });
             // Elimination
             }).then(res => {
-                supprimerLDAP(user, config.key_id+"="+gid+","+config.dn_groups);
+                supprimerLDAP(user, ldapConfig.key_id+"="+gid+","+ldapConfig.dn_groups);
             }).then(res => { if (res) {resolve(true); }});
         });
     }
@@ -886,21 +886,21 @@ class SuperAdministrateurConnecte extends AdministrateurConnecte {
     
             // uid de base généré à partir de nom et prénom, plus potentiellement promo et un offset
             // MEF mélange de Promise et de fonction standard
-            genererUid(user, data['givenName'],data['lastName'],data['promotion']).then(id => { vals[config.key_id]=id; } );
+            genererUid(user, data['givenName'],data['lastName'],data['promotion']).then(id => { vals[ldapConfig.key_id]=id; } );
     
             // Ecriture de toutes les valeurs directement inscrites dans le LDAP (in pour input)
             // Génère une erreur si un champ n'est pas rempli
-            config.user.direct_input.forEach(key_att => vals[config.user[key_att]]=data[key_att]);
+            ldapConfig.user.direct_input.forEach(key_att => vals[ldapConfig.user[key_att]]=data[key_att]);
     
             // Appel à la fonction de base
-            ajouterLDAP(user, config.key_id+"="+vals[config.key_id]+","+config.dn_users, vals).then( res => {
+            ajouterLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.key_id]+","+ldapConfig.dn_users, vals).then( res => {
                 // Modifications multiples pour avoir plusieurs champs de même type ; boucle sur les attributs multiples (d'où mul)
-                config.user.muliple_input.forEach(key_att => {
+                ldapConfig.user.muliple_input.forEach(key_att => {
                     // On rajoute chaque valeur en entrée
                     data[key_att].forEach(val => {
                         let vals2 = {};
-                        vals2[config.user[key_att]]=val;
-                        modifierLDAP(user, config.key_id+"="+vals[config.key_id]+","+config.dn_users, "add", vals2).then(res => {
+                        vals2[ldapConfig.user[key_att]]=val;
+                        modifierLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.key_id]+","+ldapConfig.dn_users, "add", vals2).then(res => {
                             if (!res) { reject(false); }
                         });
                     });
@@ -910,51 +910,51 @@ class SuperAdministrateurConnecte extends AdministrateurConnecte {
                 let vals3={};
     
                 // Création d'un nom complet lisible
-                vals3[config.user['fullName']]=data['givenName']+' '+data['lastName'].toUpperCase();
+                vals3[ldapConfig.user['fullName']]=data['givenName']+' '+data['lastName'].toUpperCase();
                 // ?!
-                vals3[config.user['password']] =  '{CRYPT}' + data['password'];
+                vals3[ldapConfig.user['password']] =  '{CRYPT}' + data['password'];
                 // Ecriture d'un surnom s'il y a lieu
                 if ((data['nickname']!=undefined)&(data['nickname']!='')) {
-                    vals3[config.user['nickname']]=data['nickname'];
+                    vals3[ldapConfig.user['nickname']]=data['nickname'];
                 }
                 // Génération id aléatoire unique
-                genererIdNum(user, config.user['id'], config.dn_users).then(id => { vals3[config.user['id']]=id; });
+                genererIdNum(user, ldapConfig.user['id'], ldapConfig.dn_users).then(id => { vals3[ldapConfig.user['id']]=id; });
                 
                 // Stockage machine ; dépend du prénom
-                vals3[config.user['directory']] = '/hosting/users/' + data['givenName'][0];
+                vals3[ldapConfig.user['directory']] = '/hosting/users/' + data['givenName'][0];
     
                 // Code root
-                vals3[config.user['cleanFullName']]=data['fullName'].replace(':', ';').toLowerCase().normalize('UFD');
+                vals3[ldapConfig.user['cleanFullName']]=data['fullName'].replace(':', ';').toLowerCase().normalize('UFD');
                 
                 // Adressage root
-                if (data['groups'].includes("on_platal")) { vals3[config.user['login']] = "/bin/bash"; }
-                else  { vals3[config.user['login']] = "/sbin/nologin"; }
+                if (data['groups'].includes("on_platal")) { vals3[ldapConfig.user['login']] = "/bin/bash"; }
+                else  { vals3[ldapConfig.user['login']] = "/sbin/nologin"; }
                 
                 // Permissions BR
-                vals3[config.user['readPerm']] = 'br.*,public.*';
-                if (data['readPerm'].length>0) { vals3[config.user['readPerm']] += ',' + data['readPerm']; }
-                vals3[config.user['writePerm']] = 'br.*,!br.blague-du-jour,public.*,!br.campagnekes';
-                if (data['writePerm'].length>0) { vals3[config.user['readPerm']] += ',' + data['writePerm']; }
+                vals3[ldapConfig.user['readPerm']] = 'br.*,public.*';
+                if (data['readPerm'].length>0) { vals3[ldapConfig.user['readPerm']] += ',' + data['readPerm']; }
+                vals3[ldapConfig.user['writePerm']] = 'br.*,!br.blague-du-jour,public.*,!br.campagnekes';
+                if (data['writePerm'].length>0) { vals3[ldapConfig.user['readPerm']] += ',' + data['writePerm']; }
     
                 // Valeur nécessaire mais inutile
-                vals3[config.user['idNum']] ='5000';
+                vals3[ldapConfig.user['idNum']] ='5000';
     
                 // Inscription des valeurs calculées
-                modifierLDAP(user, config.key_id+"="+vals[config.user['hruid']]+","+config.dn_users, "add", vals3).then(res => {
+                modifierLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.user['hruid']]+","+ldapConfig.dn_users, "add", vals3).then(res => {
                     if (!res) { reject(false); }
                 });
     
                 ["posixAccount", "shadowAccount", "inetOrgPerson", "brAccount"].forEach(cst => {
                     let val3={};
-                    vals3[config.user['class']]=cst;
-                    modifierLDAP(user, config.key_id+"="+vals[config.user['hruid']]+","+config.dn_users, "add", vals3).then(res => {
+                    vals3[ldapConfig.user['class']]=cst;
+                    modifierLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.user['hruid']]+","+ldapConfig.dn_users, "add", vals3).then(res => {
                         if (!res) { reject(false); }
                     });
                 });
     
                 // Utilisation des fonctions adaptées pour assurer la cohérence de l'ensemble
-                data['groupsIsMember'].forEach(gid => { this.ajouterMembreGroupe(user, vals[config.key_id], gid); });
-                data['groupsIsAdmin'].forEach(gid => { this.ajouterAdministrateurGroupe(user, vals[config.key_id], gid); });
+                data['groupsIsMember'].forEach(gid => { this.ajouterMembreGroupe(user, vals[ldapConfig.key_id], gid); });
+                data['groupsIsAdmin'].forEach(gid => { this.ajouterAdministrateurGroupe(user, vals[ldapConfig.key_id], gid); });
     
                 resolve(true);
             });
@@ -978,13 +978,13 @@ class SuperAdministrateurConnecte extends AdministrateurConnecte {
         return new Promise((resolve, reject) => {
             // Gestion des groupes d'abord
             this.getUser(user, uid).then(profil => {
-                profil[config.user['groups']].forEach(gid => {
+                profil[ldapConfig.user['groups']].forEach(gid => {
                     this.isGroupAdmin(user, uid, gid).then(res => {
                         if (this.la.includes(res)) { this.supprimerAdministrateurGroupe(user, uid, gid); }
                     }).then(res => { this.removeGroupMember(user, uid, gid); });
                 });
             // Elimination
-            }).then(res => { supprimerLDAP(user, config.key_id+"="+uid+","+config.dn_users); });
+            }).then(res => { supprimerLDAP(user, ldapConfig.key_id+"="+uid+","+ldapConfig.dn_users); });
         });
     }
 }
diff --git a/src/server.js b/src/server.ts
similarity index 78%
rename from src/server.js
rename to src/server.ts
index f931c3a1e181d96ba678fbb82c15b2294baa4b73..3153aa6f0751bf17e7417b60793c5f0a63591696 100644
--- a/src/server.js
+++ b/src/server.ts
@@ -4,12 +4,11 @@
  * La configuration inclut tout le _middleware_ définissant les API et les services
  * nécessaire utilisés, comme `express-session`, GraphiQL, GraphQL Voyager.
  * 
- * TODO: changer cette description... ^
- * TODD: qu'arrive-t-il aux requetes avec un cookie expire? elles ne sont traitees ni par passport.session() ni par passport.authenticate('ldapauth')...
+ * @todo changer cette description... ^
+ * @todo qu'arrive-t-il aux requetes avec un cookie expire? elles ne sont traitees ni par passport.session() ni par passport.authenticate('ldapauth')...
  * 
  * @author manifold, kadabra
-*/
-
+ */
 import express from 'express';
 import bodyParser from 'body-parser';
 // packages pour graphql
@@ -30,10 +29,10 @@ import favicon from 'serve-favicon';
 import morgan from 'morgan';
 // packages pour pouvoir importer depuis des fichiers de config
 import path from 'path';
-import fs from 'fs';
 
-import './config_passport';
+import { ldapConfig, credentialsConfig } from './ldap/config';
 
+const { dn, passwd } = credentialsConfig;
 
 const app = express(); // "The app object conventionally denotes the Express application" (https://expressjs.com/en/4x/api.html#app)
 
@@ -44,17 +43,6 @@ app.use(bodyParser.urlencoded({ //parses bodies of media type "application/x-www
 }));
 app.use(cookieParser()); //parses Cookie header and populate req.cookies with an object keyed by the cookie names. was necessary for express-session before its v1.5.0. on peut probablement l'enlever desormais.
 
-//GHETTO
-// Config de passport pour l'authentification ldap. 
-// Ne fait que *configurer* passport pour la strategie 'ldap' (pas d'incidence sur la strategie 'session' normalement)
-import './config_passport.js';
-
-
-
-/**
- * @desc TRUCS DIVERS
- */
-
 // cache le fait que l'application tourne sous Express dans le header HTTP.
 app.disable('x-powered-by');
 // Morgan is middleware for logging requests
@@ -65,40 +53,41 @@ app.use(favicon(path.resolve('./', 'assets', 'favicon.ico')));
 app.use('/assets', express.static(path.resolve('./', 'assets')));
 
 /**
- * FIN TRUCS DIVERS
+ * @desc AUTHENTIFICATION POUR LES REQUETES POSSEDANT UN COOKIE ET PROVENANT D'UN UTILISATEUR DEJA AUTHENTIFIE
+ * Remarque: introduit aussi les middlewares session et passport, 
+ * qui sont aussi utiles pour l'authentification dans les autres cas.
  */
 
-
-
-
-
 /**
- * @desc AUTHENTIFICATION POUR LES REQUETES POSSEDANT UN COOKIE ET PROVENANT D'UN UTILISATEUR DEJA AUTHENTIFIE
- * Remarque: introduit aussi les middlewares session et passport, qui sont aussi utiles pour l'authentification dans les autres cas.
+ * WTF??? why is sessionSecret in ldap_config.json? it has nothing to do with ldap.
+ * @todo FIX
  */
 
-const configPath = path.resolve('./', 'ldap_config.json');
-const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
-// WTF??? why is sessionSecret in ldap_config.json? it has nothing to do with ldap. TODO
-
-// defines parameters for *session store*. (adds field req.session and do some magic stuff)
-// basically, searches for a session matching the received cookie and, if found, adds field req.blasomethingbla containing serialized object representing user (i.e. similar to what passport.serializeUser() could produce)
-// TODO: it is important to configure this right!!! please check out https://www.npmjs.com/package/express-session and make sure you understand the way session is stored. (en vrai c'est vraiment important...)
-app.use(session({
-    secret: config.sessionSecret,
+/**
+/* defines parameters for *session store*. (adds field req.session and do some magic stuff)
+ * basically, searches for a session matching the received cookie and, if found, adds field req.blasomethingbla containing serialized
+ * object representing user (i.e. similar to what passport.serializeUser() could produce)
+ * @todo do this right
+ * it is important to configure this right!!! please check out https://www.npmjs.com/package/express-session 
+ * and make sure you understand the way session is stored. (en vrai c'est vraiment important...)
+ */
+ app.use(session({
+    secret: ldapConfig.sessionSecret,
     resave: true,
     saveUninitialized: false,
     //store: // TODO: change this. express-session doc warns that default value is ok to use for development only
 }));
-app.use(passport.initialize()); //initialize Passport. (adds hidden field req._passport and do some magic stuff)
+app.use(passport.initialize());
+//initialize Passport. (adds hidden field req._passport and do some magic stuff)
 //GHETTO
 //app.use(passport.session()); //this is equivalent to app.use(passport.authenticate('session'))
+//this is equivalent to app.use(passport.authenticate('session'))
 app.use(passport.session(), (req, res, next)=>{
-    console.log("Used passport.session()");
-    console.log(`passport.session() found user: ${req.user ? req.user.uid : "none"}`);
-    console.log("passport.session() user is authenticated:", req.isAuthenticated());
+    console.log(
+        `passport.session: found user: ${req.user ? req.user.uid : "none"}
+                             authenticated: ${req.isAuthenticated()}`);
     next();
-}); //this is equivalent to app.use(passport.authenticate('session'))
+}); 
 // *aucun* effet sur les requetes n'ayant pas ete reconnues par app.use(session(...)) (e.g. les requetes sans cookie ou les requetes avec cookie expired). source: lecture directe du code passport/lib/strategies/session.js sur github... :/
 
 /*
@@ -108,13 +97,6 @@ app.use((req, res, next) => {
 });
 */
 
-/**
- * FIN AUTHENTIFICATION POUR LES REQUETES POSSEDANT UN COOKIE ET PROVENANT D'UN UTILISATEUR DEJA AUTHENTIFIE
- */
-
-
-
-
 
 /**
  * @desc AUTHENTIFICATION POUR LES REQUETES DE CONNEXION VIA LDAP VENANT DU FRONT
@@ -122,21 +104,19 @@ app.use((req, res, next) => {
  * i.e. quand l'utilisateur submit le formulaire de login avec ses identifiants/mdp dans le front
  * Remarque: configure aussi passport pour l'authentification ldap, ce qui est aussi utile pour les requetes de connexion via ldap venant de adminview
  */
-
-const FRONTEND_SERVER_URL = 'change this to frontend server IP address';
-const FRONTEND_SERVER_URL_LOCAL = 'http://localhost:8888';
+const FRONTEND_SERVER_URL = process.env.FRONTEND_SERVER_URL || 'http://localhost:8888';
 
 // Options de configuration pour le _middleware_ `cors`.
 // CORS = Cross Origin Resource Sharing
 const corsOptions = {
-    origin: FRONTEND_SERVER_URL_LOCAL, // Configures the Access-Control-Allow-Origin CORS header. i.e. specifies that sigma-back wants to make resources accessible to this site (and this site only)
+    origin: FRONTEND_SERVER_URL, // Configures the Access-Control-Allow-Origin CORS header. i.e. specifies that sigma-back wants to make resources accessible to this site (and this site only)
     credentials: true // Configures the Access-Control-Allow-Credentials CORS header. i.e. allows cookies to be included on cross-origin requests
 };
 app.use(cors(corsOptions));
  
 //GHETTO
 // Config de passport pour l'authentification ldap. Ne fait que *configurer* passport (aucun passport.authenticate() n'est appele, par exemple)
-import './config_passport.js';
+import './config_passport';
 
 //with custom callback:
 //http://www.passportjs.org/docs/authenticate/#custom-callback
@@ -176,8 +156,9 @@ app.post('/login', (req, res, next) => {
                 // return next(err); // handle error? or drop request and answer with res.json()?
             }
             // If all went well
-            console.log("| Authentication succeeded! :-)");
-            // passport.authenticate automatically includes a Set-Cookie HTTP header in the response. The JSON body is just to signal the frontend that all went well
+            console.log("| Authentication succeeded! :)");
+            // passport.authenticate automatically includes a Set-Cookie HTTP header in 
+            // the response. The JSON body is just to signal the frontend that all went well
             return res.status(200).json({
                 message: 'Authentication succeeded',
                 authSucceeded: true
@@ -203,16 +184,9 @@ app.post('/login',
 );
 */
 
-/**
- * FIN AUTHENTIFICATION POUR LES REQUETES DE CONNEXION VIA LDAP VENANT DU FRONT
- */
-
-
 /**
  * @desc API GRAPHQL
  */
-
-import { dn, passwd } from "../ldap_connexion_config.json"; // default bind user
 const environment = process.env.NODE_ENV || 'development';
 
 app.use('/graphql', 
@@ -222,9 +196,11 @@ app.use('/graphql',
         let password;
 
         console.log("Responding to graphql request...");
-        console.log(`| User: ${req.user ? req.user.uid : "none"}`);
-        console.log(`| Authorization: ${req.headers.authorization}`);
-        console.log("| User is authenticated:",req.isAuthenticated());
+        console.log(`
+            | User: ${req.user ? req.user.uid : "none"}
+            | Authorization: ${req.headers.authorization}
+            | Authenticated: ${req.isAuthenticated()}
+            `.trim());
         
         if(req.isAuthenticated()) {
             console.log("graphql API is receiving a request from an authenticated user! \\o/");
@@ -240,7 +216,7 @@ app.use('/graphql',
             uid = dn.split("=")[1].split(",")[0];
             password = passwd;
         }
-
+        
         return {
             schema,
             graphiql: environment == 'development', // gives access to GraphiQL if req comes from browser (je crois)
@@ -293,9 +269,5 @@ app.get('/*',
     ((req, res, next) => res.redirect('/adminview'))
 );
 
-/**
- * FIN SETUP DE ADMINVIEW, L'INTERFACE ADMIN DES BDD
- */
-
 
 export default app;
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..6d8e02665c7c6babd9fb1aead695ed1ca929ea23
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,15 @@
+{
+    "compilerOptions": {
+        "module": "commonjs",
+        "esModuleInterop": true,
+        "target": "es6",
+        "moduleResolution": "node",
+        "sourceMap": true,
+        "outDir": "build",
+        "resolveJsonModule": true,
+    },
+    "include": [
+        "src/**/*",
+        "db/**/*"
+    ]
+}
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
index 47ae22d5d75574d81dfb3e76453e20a4d120b9af..33696452d9956d7e0c177f5c4b17e633bf203f7f 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -3,40 +3,46 @@ const nodeExternals = require('webpack-node-externals');
 const CopyWebpackPlugin = require('copy-webpack-plugin');
 
 const config = {
-    entry: './src/index.js',
+    entry: './src/index.ts',
 
     target: 'node',
     node: {
         __dirname: false
     },
-    
-    output: {
-        path: path.resolve(__dirname, 'build'),
-        publicPath: '/assets/',
-        filename: 'bundle.js'
-    },
-
-    devtool: 'source-map',
-    
-    externals: [nodeExternals()],
+    //devtool: 'inline-source-map',
+    externals: [
+        nodeExternals(),
+        {
+            ldapConfig: './ldap_config.json',
+            credentialsConfig: './ldap_connexion_config.json'
+        }
+    ],
     
     module: {
         rules: [{
             test: /\.js$/,
             use: ['eslint-loader']
+        },{
+            test: /\.ts$/,
+            use: ['ts-loader'],
         },{
             test: /\.css$/,
             use: ['style-loader', 'css-loader']
+        }, {
+            type: 'javascript/auto',
+            test: /\.json$/,
+            use: ['file-loader']
         },{
             test: /\.(png|jpg|ico)$/,
-            exclude: /node_modules/,
             loader: 'file-loader',
             options: {
                 limit: 10000
             }
         }]
     },
-
+    resolve: {
+        extensions: ['.ts', '.js']
+    },
     plugins: [
         new CopyWebpackPlugin([{
             from: 'src/css',
@@ -46,7 +52,13 @@ const config = {
             to: 'views'
         }]
         )
-    ]
+    ],
+
+    output: {
+        path: path.resolve(__dirname, 'build'),
+        publicPath: '/assets/',
+        filename: 'bundle.js'
+    },
 };
 
 module.exports = config;
\ No newline at end of file