diff --git a/authentication-module/src/main/java/net/jami/jams/authmodule/UserAuthenticationModule.java b/authentication-module/src/main/java/net/jami/jams/authmodule/UserAuthenticationModule.java
index 0b096eb5f8af288f1dc4db2c2e6e5244042b80f5..5bb5a067e5c095b1705c2e2ca928122c5f38b812 100644
--- a/authentication-module/src/main/java/net/jami/jams/authmodule/UserAuthenticationModule.java
+++ b/authentication-module/src/main/java/net/jami/jams/authmodule/UserAuthenticationModule.java
@@ -37,6 +37,7 @@ import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.common.objects.user.User;
 import net.jami.jams.common.utils.LibraryLoader;
 import net.jami.jams.common.utils.X509Utils;
+import org.bouncycastle.cert.X509CRLHolder;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -160,8 +161,29 @@ public class UserAuthenticationModule implements AuthenticationModule {
     }
 
     @Override
-    public AuthTokenResponse authenticateUser(X509Certificate[] certificates) {
-        return null;
+    public AuthTokenResponse authenticateUser(X509Certificate[] certificates, X509CRLHolder crl,
+                                              X509Certificate ca) {
+        //Extract the username for the certificate and verify that it is not revoked.
+        X509Certificate clientCert = certificates[0];
+        try {
+            //Check if the certificate is even valid.
+            clientCert.checkValidity();
+            //Check if the certificate was provided by a valid authority.
+            clientCert.verify(ca.getPublicKey());
+            //Here we need to make a request to the CRL to find out if it has been revoked.
+            if(crl.getRevokedCertificate(clientCert.getSerialNumber()) != null) return null;
+            //If the above cases have passed, then this user is indded valid.
+            //This is yet to be confirmed.
+            String username = clientCert.getSubjectDN().getName();
+            StatementList statementList = new StatementList();
+            StatementElement statementElement = new StatementElement("username","=",username,"");
+            statementList.addStatement(statementElement);
+            User user = datastore.getUserDao().getObjects(statementList).get(0);
+            return tokenController.getToken(user);
+        }
+        catch (Exception e){
+            return null;
+        }
     }
 
     @Override
@@ -180,7 +202,7 @@ public class UserAuthenticationModule implements AuthenticationModule {
             return source.test();
         }
         catch (Exception e){
-            log.error("The testing of the source was unsuccessful!");
+            log.error("The testing of the source was unsuccessful: " + e.toString());
             return false;
         }
     }
diff --git a/clean.sh b/clean.sh
new file mode 100755
index 0000000000000000000000000000000000000000..96b22e13f573a4106e1eb7357e3c91de3ad662c0
--- /dev/null
+++ b/clean.sh
@@ -0,0 +1,5 @@
+rm -rf jams
+rm derby.log
+rm oauth.key
+rm oauth.pub
+
diff --git a/datastore/src/main/java/net/jami/datastore/dao/AbstractDao.java b/datastore/src/main/java/net/jami/datastore/dao/AbstractDao.java
index ffbca27b868807ce98d7fc2ef74ebb7ab41c2904..0470e8a488e3f3c5d479b09abcba436c82bc46df 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/AbstractDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/AbstractDao.java
@@ -26,6 +26,7 @@ import lombok.Getter;
 import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
 import net.jami.datastore.main.DataStore;
+import net.jami.jams.common.dao.DeleteStatementBuilder;
 import net.jami.jams.common.dao.SelectStatementBuilder;
 import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.dao.UpdateStatementBuilder;
@@ -34,7 +35,6 @@ import net.jami.jams.common.dao.connectivity.SQLConnection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.util.ArrayList;
-import java.util.LinkedHashMap;
 import java.util.List;
 
 @Slf4j
@@ -46,7 +46,6 @@ public abstract class AbstractDao<T> {
     private Class<T> tClass;
 
     public abstract boolean storeObject(T object);
-    public abstract boolean deleteObject(LinkedHashMap<String,String> constraints);
 
     public List<T> getObjects(StatementList constraints){
         List<T> result = new ArrayList<>();
@@ -82,4 +81,20 @@ public abstract class AbstractDao<T> {
             DataStore.connectionPool.returnConnection(connection);
         }
     }
+
+    public boolean deleteObject(StatementList delete){
+        SQLConnection connection = DataStore.connectionPool.getConnection();
+        try{
+            PreparedStatement ps = DeleteStatementBuilder.buildStatement(tableName,delete,connection);
+            return ps.executeUpdate() != 0;
+        }
+        catch (Exception e){
+            log.error("An error has occurred while trying to fetch a device: " + e.toString());
+            return false;
+        }
+        finally {
+            DataStore.connectionPool.returnConnection(connection);
+        }
+    }
+
 }
diff --git a/datastore/src/main/java/net/jami/datastore/dao/ContactDao.java b/datastore/src/main/java/net/jami/datastore/dao/ContactDao.java
index 1e33d86b870963fd13319a7f4ef1047d97fceb23..729ba671097e9530ed33b85d86a5207a8c7aac62 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/ContactDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/ContactDao.java
@@ -22,25 +22,55 @@
 */
 package net.jami.datastore.dao;
 
-import net.jami.jams.common.dao.StatementList;
+import lombok.extern.slf4j.Slf4j;
+import net.jami.datastore.main.DataStore;
+import net.jami.jams.common.dao.connectivity.SQLConnection;
 import net.jami.jams.common.objects.contacts.Contact;
 
-import java.util.LinkedHashMap;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
 
+@Slf4j
 public class ContactDao extends AbstractDao<Contact> {
 
-    @Override
-    public boolean storeObject(Contact object) {
-        return false;
-    }
-
-    @Override
-    public boolean deleteObject(LinkedHashMap<String, String> constraints) {
-        return false;
+    public ContactDao() {
+        SQLConnection connection = DataStore.connectionPool.getConnection();
+        try {
+            this.setTableName("contacts");
+            this.setTClass(Contact.class);
+            String createTable = "CREATE TABLE contacts (" +
+                "owner varchar(255), " +
+                "uri varchar(255)," +
+                "displayName varchar(255),"+
+                "PRIMARY KEY (owner,uri))";
+            PreparedStatement ps = connection.getConnection().prepareStatement(createTable);
+            ps.execute();
+        }
+        catch (SQLException e){
+            log.error("Could not create the contacts table with error " + e.getMessage());
+        }
+        finally {
+            DataStore.connectionPool.returnConnection(connection);
+        }
     }
 
     @Override
-    public boolean updateObject(StatementList update, StatementList constraints) {
-        return false;
+    public boolean storeObject(Contact object) {
+        SQLConnection connection = DataStore.connectionPool.getConnection();
+        try{
+            PreparedStatement ps = connection.getConnection().prepareStatement("INSERT INTO contacts " +
+                "(owner, uri, displayName) " +
+                "VALUES " +
+                "(?, ?, ?)");
+            ps = object.getInsert(ps);
+            return ps.executeUpdate() != 0;
+        }
+        catch (Exception e){
+            log.error("An error has occurred while trying to store a user: " + e.toString());
+            return false;
+        }
+        finally {
+            DataStore.connectionPool.returnConnection(connection);
+        }
     }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/dao/DeviceDao.java b/datastore/src/main/java/net/jami/datastore/dao/DeviceDao.java
index 6af5941495ee0edb7f6a933f9a93004e25a63f06..bf3ab3fe8788a0f87e30c852fda8cb9f87b22b1e 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/DeviceDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/DeviceDao.java
@@ -30,7 +30,6 @@ import net.jami.jams.common.objects.devices.Device;
 
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
-import java.util.LinkedHashMap;
 
 @Slf4j
 public class DeviceDao extends AbstractDao<Device> {
@@ -67,7 +66,7 @@ public class DeviceDao extends AbstractDao<Device> {
                     "VALUES " +
                     "(?, ?, ?, ?, ?)");
             ps = object.getInsert(ps);
-            return ps.execute();
+            return ps.executeUpdate() != 0;
         }
         catch (Exception e){
             log.error("An error has occurred while trying to store a user: " + e.toString());
@@ -78,11 +77,6 @@ public class DeviceDao extends AbstractDao<Device> {
         }
     }
 
-    @Override
-    public boolean deleteObject(LinkedHashMap<String, String> constraints) {
-        return false;
-    }
-
     @Override
     public boolean updateObject(StatementList update, StatementList constraints) {
         return false;
diff --git a/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java b/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java
index 7cb9e1587a8ab624870a486a862c109cc27722be..16ab23ef28997befc1e5af3259f16f6a9d2a5fdd 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java
@@ -30,7 +30,6 @@ import net.jami.jams.common.objects.system.SystemAccount;
 
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
-import java.util.LinkedHashMap;
 
 @Slf4j
 public class SystemDao extends AbstractDao<SystemAccount> {
@@ -65,7 +64,7 @@ public class SystemDao extends AbstractDao<SystemAccount> {
                     "VALUES " +
                     "(?, ?, ?)");
             ps = object.getInsert(ps);
-            return ps.execute();
+            return ps.executeUpdate() != 0;
         }
         catch (Exception e){
             log.error("An error has occurred while trying to store a system entity: " + e.toString());
@@ -76,11 +75,6 @@ public class SystemDao extends AbstractDao<SystemAccount> {
         }
     }
 
-    @Override
-    public boolean deleteObject(LinkedHashMap<String, String> constraints) {
-        return false;
-    }
-
     @Override
     public boolean updateObject(StatementList update, StatementList constraints) {
         return false;
diff --git a/datastore/src/main/java/net/jami/datastore/dao/UserDao.java b/datastore/src/main/java/net/jami/datastore/dao/UserDao.java
index e5b75b84902df1a90abb9fd8f39c77c4985d5ac6..02db13401ea14315cf8b65b82ab4426889831b71 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/UserDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/UserDao.java
@@ -29,7 +29,6 @@ import net.jami.jams.common.objects.user.User;
 
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
-import java.util.LinkedHashMap;
 
 @Slf4j
 public class UserDao extends AbstractDao<User> {
@@ -73,7 +72,7 @@ public class UserDao extends AbstractDao<User> {
                     "VALUES " +
                     "(?, ?, ?, ?, ?, ?, ?,?, ?,?, ?)");
             ps = object.getInsert(ps);
-            return ps.execute();
+            return ps.executeUpdate() != 0;
         }
         catch (Exception e){
             log.error("An error has occurred while trying to store a user: " + e.toString());
@@ -83,10 +82,4 @@ public class UserDao extends AbstractDao<User> {
             DataStore.connectionPool.returnConnection(connection);
         }
     }
-
-
-    @Override
-    public boolean deleteObject(LinkedHashMap<String, String> constraints) {
-        return false;
-    }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/dao/UserProfileDAO.java b/datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java
similarity index 90%
rename from datastore/src/main/java/net/jami/datastore/dao/UserProfileDAO.java
rename to datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java
index 1f1d4096fde5916969f9a52fb243c8ca9231d854..e2df45111a4afc700662fdea0e68558306ca559e 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/UserProfileDAO.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java
@@ -29,13 +29,12 @@ import net.jami.jams.common.objects.user.UserProfile;
 
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
-import java.util.LinkedHashMap;
 
 @Slf4j
-public class UserProfileDAO extends AbstractDao<UserProfile> {
+public class UserProfileDao extends AbstractDao<UserProfile> {
 
     //Fis this to include the fields from AD/LDAP.
-    public UserProfileDAO() {
+    public UserProfileDao() {
         SQLConnection connection = DataStore.connectionPool.getConnection();
         try {
             this.setTableName("local_directory");
@@ -60,9 +59,4 @@ public class UserProfileDAO extends AbstractDao<UserProfile> {
     public boolean storeObject(UserProfile object) {
         return false;
     }
-
-    @Override
-    public boolean deleteObject(LinkedHashMap<String, String> constraints) {
-        return false;
-    }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/main/DataStore.java b/datastore/src/main/java/net/jami/datastore/main/DataStore.java
index 41ed66eefbed2b3d301b0ed153d381eab663ba7f..852cdaeafea5f50450e8183b5342a1c0decf2418 100644
--- a/datastore/src/main/java/net/jami/datastore/main/DataStore.java
+++ b/datastore/src/main/java/net/jami/datastore/main/DataStore.java
@@ -24,6 +24,7 @@ package net.jami.datastore.main;
 
 import lombok.Getter;
 import lombok.Setter;
+import net.jami.datastore.dao.ContactDao;
 import net.jami.datastore.dao.DeviceDao;
 import net.jami.datastore.dao.SystemDao;
 import net.jami.datastore.dao.UserDao;
@@ -46,6 +47,7 @@ public class DataStore implements AuthenticationSource {
     private UserDao userDao;
     private DeviceDao deviceDao;
     private SystemDao systemDao;
+    private ContactDao contactDao;
 
     //Implicitly connect to debry.
     public DataStore(String connectionString) {
@@ -53,6 +55,7 @@ public class DataStore implements AuthenticationSource {
         userDao = new UserDao();
         deviceDao = new DeviceDao();
         systemDao = new SystemDao();
+        contactDao = new ContactDao();
     }
 
     public boolean userExists(String username){
diff --git a/server.key b/developer-tools/samples/server.key
similarity index 100%
rename from server.key
rename to developer-tools/samples/server.key
diff --git a/server.pem b/developer-tools/samples/server.pem
similarity index 100%
rename from server.pem
rename to developer-tools/samples/server.pem
diff --git a/integration-test/buildcert.sh b/integration-test/buildcert.sh
new file mode 100755
index 0000000000000000000000000000000000000000..42d11fd0b8877dd9483fe91037d53f7abed96f8b
--- /dev/null
+++ b/integration-test/buildcert.sh
@@ -0,0 +1,3 @@
+openssl req -x509 -newkey rsa:4096 -days 3650 -nodes -keyout user.key -out user.crt -subj "/CN=fsidokhine"
+openssl pkcs12 -export -out user.pfx -inkey user.key -in user.crt
+curl -d -k -v -X POST "https://localhost:8080/api/auth/login" -E user.pfx --pass abc123
diff --git a/integration-test/contact-test.py b/integration-test/contact-test.py
new file mode 100644
index 0000000000000000000000000000000000000000..6bf97644aa0e9e9960c34da5f0c8c523b8c79ba3
--- /dev/null
+++ b/integration-test/contact-test.py
@@ -0,0 +1,48 @@
+import json
+import requests
+import urllib.parse
+
+header = {}
+header['Content-type'] = "application/json"
+
+response = requests.post('http://localhost:8080/api/auth/login',data={"username":"fsidokhine","password":"mes87hesm97daa"})
+if response.status_code == 200:
+    token = json.loads(response.text)['access_token']
+
+header = {}
+header['Bearer'] = token
+
+
+#Create two contacts
+data = {}
+data['uri'] = "jami://71828737748484"
+data['displayName'] = "Felix"
+response = requests.put("http://localhost:8080/api/auth/contacts",headers=header,data=json.dumps(data))
+print(response.status_code)
+print(response.text)
+
+data = {}
+data['uri'] = "jami://71828737748485"
+data['displayName'] = "Adrien"
+response = requests.put("http://localhost:8080/api/auth/contacts",headers=header,data=json.dumps(data))
+print(response.status_code)
+print(response.text)
+
+#Get both contacts
+
+response = requests.get("http://localhost:8080/api/auth/contacts",headers=header)
+print(response.status_code)
+print(response.text)
+
+#Delete a contact
+params = {'uri':'jami://71828737748485'}
+p = urllib.parse.urlencode(params,safe='')
+response = requests.delete("http://localhost:8080/api/auth/contacts?" + p,headers=header)
+print(response.status_code)
+print(response.text)
+#
+##Get contact
+#
+response = requests.get("http://localhost:8080/api/auth/contacts",headers=header)
+print(response.status_code)
+print(response.text)
\ No newline at end of file
diff --git a/integration-test/install-server.py b/integration-test/install-server.py
index 9d97dd5e45806479bef5c2896b45969f9ac6da60..233ab92a85e1719badd543e638d644196d6d7409 100644
--- a/integration-test/install-server.py
+++ b/integration-test/install-server.py
@@ -1,6 +1,8 @@
 import json
 import requests
 
+baseUri = "https://localhost:8080"
+
 data = {}
 data['username'] = "admin"
 data['password'] = "abc123"
@@ -8,7 +10,7 @@ data['password'] = "abc123"
 header = {}
 header['Content-type'] = "application/json"
 
-response = requests.put('http://localhost:8080/api/install/start',data=json.dumps(data),headers=header)
+response = requests.put(baseUri + '/api/install/start',data=json.dumps(data),headers=header,verify=False)
 if response.status_code == 200:
     print("Succesfully created the administrative user!")
     token = json.loads(response.text)['access_token']
@@ -24,7 +26,7 @@ data['fields']['commonName'] = "TEST CA"
 data['fields']['country'] = "FR"
 data['fields']['lifetime'] = 10000000
 
-response = requests.post('http://localhost:8080/api/install/ca',data=json.dumps(data),headers=header)
+response = requests.post(baseUri + '/api/install/ca',data=json.dumps(data),headers=header,verify=False)
 if response.status_code == 200:
     print("Added CA parameters!")
 else:
@@ -52,7 +54,7 @@ data['ldapSettings']['fieldMappings']['facsimileTelephoneNumber'] = "FaxNumber"
 data['ldapSettings']['fieldMappings']['extensionName'] = "PhoneNumberExtension"
 data['ldapSettings']['fieldMappings']['o'] = "Organization"
 
-response = requests.post('http://localhost:8080/api/install/auth',data=json.dumps(data),headers=header)
+response = requests.post(baseUri + '/api/install/auth',data=json.dumps(data),headers=header,verify=False)
 if response.status_code == 200:
     print("Added LDAP parameters!")
 else:
@@ -65,12 +67,12 @@ data['crlLifetime'] = 100000
 data['userLifetime'] = 100000
 data['deviceLifetime'] = 100000
 
-response = requests.post('http://localhost:8080/api/install/settings',data=json.dumps(data),headers=header)
+response = requests.post(baseUri + '/api/install/settings',data=json.dumps(data),headers=header,verify=False)
 
 #This completes the install, now we'll try to enroll.
 
 data = {}
-response = requests.post('http://localhost:8080/api/auth/login',data={"username":"fsidokhine","password":"mes87hesm97daa"})
+response = requests.post(baseUri + '/api/auth/login',data={"username":"fsidokhine","password":"mes87hesm97daa"},verify=False)
 if response.status_code == 200:
     token = json.loads(response.text)['access_token']
 
@@ -110,25 +112,31 @@ oTBLLnRmdyi/SFreL5WRhMm67DHne08LCqnkzEVwMIUECN5f2mkx9KP3BrsXuH2W
 sxMmX+s/PapsdSyUJ2g3hAf6Iv5m0pcUeQ==
 -----END NEW CERTIFICATE REQUEST-----'''
 
-response = requests.post('http://localhost:8080/api/auth/device',headers=header,data=json.dumps(data))
+response = requests.post(baseUri + '/api/auth/device',headers=header,data=json.dumps(data),verify=False)
 print(response.status_code)
 print(response.text)
 
 print(token)
 
-response = requests.get("http://localhost:8080/api/nameserver/name/aberaud",headers=header)
+response = requests.get("http://localhost:8080/api/nameserver/name/aberaud",headers=header,verify=False)
 print(response.status_code)
 print(response.text)
 
 
-response = requests.get("http://localhost:8080//api/auth/directories",headers=header)
+response = requests.get("http://localhost:8080//api/auth/directories",headers=header,verify=False)
 print(response.status_code)
 print(response.text)
 
-response = requests.get("http://localhost:8080/api/auth/user",headers=header)
+response = requests.get("http://localhost:8080/api/auth/user",headers=header,verify=False)
 print(response.status_code)
 print(response.text)
 
-response = requests.post("http://localhost:8080/api/update",headers=header)
+print("Getting user profile as vcard")
+response = requests.get("http://localhost:8080/api/auth/directory/entry?username=aberaud&format=vcard",headers=header,verify=False)
+print(response.status_code)
+print(response.text)
+
+
+response = requests.post("http://localhost:8080/api/update",headers=header,verify=False)
 print(response.status_code)
 print(response.text)
diff --git a/integration-test/user.crt b/integration-test/user.crt
new file mode 100644
index 0000000000000000000000000000000000000000..43c12a3dc36e7790b4064ed3961b3d2a54fa59c2
--- /dev/null
+++ b/integration-test/user.crt
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIFCzCCAvOgAwIBAgIUFmkFCfLO2IiOp5zMv8saqdIGtbQwDQYJKoZIhvcNAQEL
+BQAwFTETMBEGA1UEAwwKZnNpZG9raGluZTAeFw0yMDA1MzExNTIzNDNaFw0zMDA1
+MjkxNTIzNDNaMBUxEzARBgNVBAMMCmZzaWRva2hpbmUwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQDVTpTBD/cyq/1qP+RSTw6blyYWmkqsdeMOvCJHAFrf
+mFhgD7cKZSGxjtsdpCgB2yFxqT11yo0uLzCSz24HYmb7ZsAVgh4PvqPVeyxIHdig
+fS79xT8nKZY+tUuZPt7A402fMqMf+E9P+NxdvPErL9yTtuHSx3uWXjsGGRI8BUr/
+W6W5Mrr9xbYaa17GeBLExGCTm3pfPsIy4TugLItxDKYGRx1Es6NBNsdBrICJDRaG
+2jNARXD5r8WBsc9GSOEuBF+LAb85eDXjV38DWHGN3eMt3Bqa6kisK2TU+P2ub8L2
+hsstEpNyxW+MC90q3cKDpZF+EA3VzNOlRxXSfNSbDQ2Ljrp9cl/PKy2zUMCApriO
+GeGFkfWD8JqUdjY/cuBE6OwtMTOeHaQD3ORGYnyiu5JOrAqNOcCyQa/NcU3g+5hl
+I1dxZIbbkRErG0fPSzlWx3nF5KRkxPS1h7ZRObKfSYN/2UNk2lmKh9N8puaqWaDJ
+rNzft050PkcZjnLpkEj+H2LIxNhJeEe95pmlDulLa/3MRAOKhJhcp49XXQ8gW+N6
+DRhfg1E/LzbVQvIrq0O03wpzmTD7V8nTc0juo3n9hTggiWOIUwNZ+grA3sb/+8nU
+nrvq1z+0bUKYApM/DDGD7E1hIl/2p4y9OhcP/b1ZdTh9OvxCmJQebox53ZNkyj/s
+jQIDAQABo1MwUTAdBgNVHQ4EFgQUIJYrdvDdXK9BVaPEonPSuxMxPu4wHwYDVR0j
+BBgwFoAUIJYrdvDdXK9BVaPEonPSuxMxPu4wDwYDVR0TAQH/BAUwAwEB/zANBgkq
+hkiG9w0BAQsFAAOCAgEAoCN0Dh/MfwnV7wjaHN8SZjgQfAcsLantjhfaUHSfhswI
+eFiuXs6V8ZIICyG70hdHoY/aoia24bwaNN/I6t9GM9SxW+5OaWDzQjm1Ph6XyF46
+/wplgVC1hbuKV4V3TyAGTVdy6TQ/d/BuHSX1pGAnq4x17pdfI/zSFxbdUCUO2j64
+4OXKg+u0gDyai3rR+38ICaEDo47ZBLdNjzXJ+qxcXOTEWErb6K7O1ccAuT6hU6rR
+Pm6SSsWLer9L9zK08pdGPOUQ2ZJYg0EeaIt4bpknpk6ueV1M/r/WUkfKYNgSZYGY
+jD/xb7TPx8qyK9pyD5SZDkp/hBPb1LybtxVMkWzAzAIDBixQujs3ygy/87cSt8W6
+/ntU4v8qqgAi+QBWtYG8H1HXeru8U5V84cjVazxy5j4mxpJ5W/hETDZc6rR3zs5B
+SIkAeVCx8MlMEGQGSWUl9JZoa/hjYsmR/dvSd8+FdGtuW8NJlNqKy8P5Qjk9BFg6
+oV4iK9sm52kQ4bYybTL8nhj9QUSn1EU3a/DC72mwQSFVYYZ4bbfMIA8zWy9x3tYt
+wqiKvLQF+6TNaAgb3i7maPNaK3Au5uKSebgIvcUJlC2daClD2cR1cfQbKdO8qq6K
+JPKcfBaByepFAyHNxCX7NRQtcbRrI4HZjrehHGnlsaMqGZMLCzbyMBA7Aml0r9Y=
+-----END CERTIFICATE-----
diff --git a/integration-test/user.key b/integration-test/user.key
new file mode 100644
index 0000000000000000000000000000000000000000..7343804708667825fe6a45e090dfd3f5d898c434
--- /dev/null
+++ b/integration-test/user.key
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDVTpTBD/cyq/1q
+P+RSTw6blyYWmkqsdeMOvCJHAFrfmFhgD7cKZSGxjtsdpCgB2yFxqT11yo0uLzCS
+z24HYmb7ZsAVgh4PvqPVeyxIHdigfS79xT8nKZY+tUuZPt7A402fMqMf+E9P+Nxd
+vPErL9yTtuHSx3uWXjsGGRI8BUr/W6W5Mrr9xbYaa17GeBLExGCTm3pfPsIy4Tug
+LItxDKYGRx1Es6NBNsdBrICJDRaG2jNARXD5r8WBsc9GSOEuBF+LAb85eDXjV38D
+WHGN3eMt3Bqa6kisK2TU+P2ub8L2hsstEpNyxW+MC90q3cKDpZF+EA3VzNOlRxXS
+fNSbDQ2Ljrp9cl/PKy2zUMCApriOGeGFkfWD8JqUdjY/cuBE6OwtMTOeHaQD3ORG
+Ynyiu5JOrAqNOcCyQa/NcU3g+5hlI1dxZIbbkRErG0fPSzlWx3nF5KRkxPS1h7ZR
+ObKfSYN/2UNk2lmKh9N8puaqWaDJrNzft050PkcZjnLpkEj+H2LIxNhJeEe95pml
+DulLa/3MRAOKhJhcp49XXQ8gW+N6DRhfg1E/LzbVQvIrq0O03wpzmTD7V8nTc0ju
+o3n9hTggiWOIUwNZ+grA3sb/+8nUnrvq1z+0bUKYApM/DDGD7E1hIl/2p4y9OhcP
+/b1ZdTh9OvxCmJQebox53ZNkyj/sjQIDAQABAoICAQC0Y2sbRiQ4PwjlVLkC/oaN
+ACsezEbASEXHzURzpRI0q0J5onCaIuJ2pSgajhujTiyfUY9/UNdKKnA6h582MXqD
+uuZQiiRgDknBHRRavJrZRmR6CdgZh2rfBzSymV+J4fBf5FPdkoGIUR4TS9jsO+Kf
+LPcW6MpUZMYnpwYrqhI9l8SztPo76HrTJuAUmbDNpIFD8yVu7MUQgDeLgoA+D4NM
+JdHTqtMyMGAb4wUkYeQeEONsxA0BqystPjDa8IE2CE7AYK7VrBpucy0fqCkH35Di
+1JPPVLg2mdAA57ypSyymjWG/cUkus1ddKR9VxApeiKNc57i7iSenS1FiG1007rn3
+M3OlFkaN/Kc84EvgPJwfK1YixU1gKTGSnKk5cAsoP3elNBKXNKeHLGo54o+eLGgR
+q0pJw6mbLyEixOigGDAtG9z9jmxqBDubj7LIFxogwNzy7dM/hgTXgcOtgd56ljwA
+ms/WbjVYi9GkoFmNjF/3Cksg5Bn2EPrcPL3z/L1IDfYVm9058FmyKa4Qe7zJa2YP
+uA+QmrKpSyG2mjVByY0ELTHqQcgLjUiRVCFfDWftaH2rUmviy61HocuyznQU0b/t
+RnhNHhiMnbNVfF4qDt3X6786gE0amE+4vtLDBXi3eeomAMBb42ti3Ui5Dc8bf3Pc
+YqoXP2bM1hOoy5clscqlRQKCAQEA6mYM+8TLon9UAC2r4P7lYGS/4v4j9GlxV5F0
+QfUZ1qfWZMI4lckBvQlys4tWzbocX9imYwbbjqpj+DTmLkfs1kNCbAlC5hvsn+hz
+mt5YVcNwjAoYfX0RnAQItjBxX8E1IbOgz6GOvLhEQcSJFUS8E92t6ZZ7AHLZiqc6
+sdpaDPimCNayxfHpXn+dE6jJ4GoZQKkGCt8W2rjBIW45mer+R9TB6GkrCa5Ok2eD
+lHC/g+/E4C16t9ABYppCXmSoEt4Rcujns185bBnWdy1haNHv+FdtMQ/qEQrtx3WL
+4TaCUNXhRPY0vXN9Zr5n5ajAJ0TmvqWpCSrUcRuEs1yUp+IDSwKCAQEA6PbvGUek
+1XK/X8Hmr/MTFHw9kp+R4I2OMl9QXr2+Uqbn5t6MIqUN5zgY7sZtvqyIU0MhYpVk
+A809lTiRtM8mWtfTJbFGzBsWsmbki+DGeb3RMT0Voon0+PPAg2qL3Fe0Pnn9mDuP
+5/luGuVFK8eGzd6402Q4gi6EwcZsWzylRGMbhjt5or0QHYMZa07kwG9PYVhAR29q
+IAWrdSsWswwoOt+K3ytvtA16KQqvjyPxz6fXNUAipMndTYp/o+J3xXtCpepZf4IU
+6dKn09bWhQA45MDVSI09BViWzjAbffUyH2DnUnsEC8ZPEeKY9a6PAr9hOdhj3vzQ
+mRv0VRMDqOKQhwKCAQEA3Httzw1INuvqSdisCpH5lPhv/sbrbyYX9TTe1IQG8AEk
+C9cdftd6iSRv/i8dUZq0wft6Vz/GGqZwLrMjqXkCcHEH87Oqd+TgaXIv/AcVtGaI
+YVHFw5R3kffBcg6TNmz422Cp7WScbSwvGGYURCtJdq5YvpZL0Ro3QtMWxOENP5JM
+K5g4xTVOPRNw32MvsaZbZpUXF/bM+qQ7FoUmLX/7+/lHBKSYVRze0IzYGjMMEsDg
+wbZF7sz74JIVx9CKwGSeqSYnfHQgAW00bRoEvKJtRX6HOVUs6ScMj0gkcY3iesMU
+iNfGuEYAOTr1Y/Od+9I18jLFk9fzyQkHg+eb9WcFjQKCAQEA1mUSrAg0GT/OAXk4
+LSsdnxerrrltjeOYPqFbHKWwdu4ls2GSQ/v0bJtCztQMgZLUrxOzsL9dWOZUS3TR
+Gz4cxTOknSalygcP/0UUBerpnXZkA9V8iKY/rbDdtdOjPTf1qB2qlaQTDuCNRPFE
+lEK+u83B+MFeA+h9wrsyU1Dfo6010nX/vhYSs6ZICWqEuNh3jFWkalmNqESvg1gR
+PtvsVioN6s5VsbVJfGXaJXhl/L4xH0+T0mX4ZXkVeKRdp3+FWZ3vmZoEVx/H1fv8
+VlBbC6KvZmKdCsN5ne3GD0hNRXVvzYdqtM9fS01niYqJEHVCK/MKDlhKPO3uETE7
+h/xiFwKCAQAWHjWxHDfSv/EAYIP+uTfvSDggVXJiN8b5dXZ7VGF7ljUg8q5jdLau
+TGiLfDTCEChu2ZsTowkeLaLMPOFq2I5F8p4AOoDTwRoNYVnMG63/fZVQU9ZsAh6D
+V0xUbMgcvlIzxG6+3sEfw7867g9jaVuDF0kE/d13B0c0Mk74SNkRcLZiz0RdvWJA
++xcFJnyhv32V7rYL1R6DtaRvnmvAeKODeJ2Sdc8pn26NUH/M8hF0TPkASBGnf2wo
+J6XcvcFLa6USB7hVX887JJgeFQCkQqyRdWmyVTio+xz4xj0w43CRKYvyn1PUYe4m
+6aIeoWpTJNW1E4sjnz7eu5ojhoYLLx2t
+-----END PRIVATE KEY-----
diff --git a/integration-test/user.pfx b/integration-test/user.pfx
new file mode 100644
index 0000000000000000000000000000000000000000..226c15ea19be8889b4c5334a3842905894795c9a
Binary files /dev/null and b/integration-test/user.pfx differ
diff --git a/jams-ca/src/main/java/net/jami/jams/ca/JamsCA.java b/jams-ca/src/main/java/net/jami/jams/ca/JamsCA.java
index 8bebfbc2eb5a8120a73f0623fbaa70d0976ebb40..543a45cbad80578a4d245c7b5f9a7c75bb1d9cf0 100644
--- a/jams-ca/src/main/java/net/jami/jams/ca/JamsCA.java
+++ b/jams-ca/src/main/java/net/jami/jams/ca/JamsCA.java
@@ -79,12 +79,13 @@ public class JamsCA implements CertificateAuthority {
         crlLifetime = config.getCrlLifetime();
         userLifetime = config.getUserLifetime();
         deviceLifetime = config.getDeviceLifetime();
-        crlWorker = new CRLWorker(CA.getPrivateKey(), CA.getCertificate());
-        try {
-            ocspWorker = new OCSPWorker(OCSP.getPrivateKey(), OCSP.getCertificate(), crlWorker);
-        }
-        catch (Exception e){
-            log.error("Could not start OCSP request processor with error {}",e.getMessage());
+        if(ca != null && ocsp != null) {
+            crlWorker = new CRLWorker(CA.getPrivateKey(), CA.getCertificate());
+            try {
+                ocspWorker = new OCSPWorker(OCSP.getPrivateKey(), OCSP.getCertificate(), crlWorker);
+            } catch (Exception e) {
+                log.error("Could not start OCSP request processor with error {}", e.getMessage());
+            }
         }
     }
 
@@ -136,4 +137,18 @@ public class JamsCA implements CertificateAuthority {
     public X509Certificate getCA() {
         return CA.getCertificate();
     }
+
+    @Override
+    public boolean shutdownThreads() {
+        //Unsafe but acceptable.
+        crlWorker.getStop().set(true);
+        crlWorker.interrupt();
+        Thread.State state = crlWorker.getState();
+        while(!state.equals(Thread.State.TERMINATED)){
+            state = crlWorker.getState();
+        }
+        crlWorker = null;
+        ocspWorker.stop();
+        return true;
+    }
 }
diff --git a/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLFileStorage.java b/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLFileStorage.java
new file mode 100644
index 0000000000000000000000000000000000000000..b8f24fc7baa304e7676e6bef0938c8c56c3c2c33
--- /dev/null
+++ b/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLFileStorage.java
@@ -0,0 +1,43 @@
+/*
+* Copyright (C) 2020 by Savoir-faire Linux
+* Authors: William Enright <william.enright@savoirfairelinux.com>
+*          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
+*          Johnny Flores <johnny.flores@savoirfairelinux.com>
+*          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
+*          Felix Sidokhine <felix.sidokhine@savoirfairelinux.com>
+*
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+package net.jami.jams.ca.workers.crl;
+
+import net.jami.jams.common.serialization.fs.FileStorage;
+import org.bouncycastle.cert.X509CRLHolder;
+
+public class CRLFileStorage extends FileStorage<X509CRLHolder> {
+
+    public CRLFileStorage(String file) {
+        super(file);
+    }
+
+    @Override
+    public X509CRLHolder getObject(byte[] bytes) throws Exception{
+        return new X509CRLHolder(bytes);
+    }
+
+    @Override
+    public byte[] getBytesFromObject(X509CRLHolder object) throws Exception {
+        return object.getEncoded();
+    }
+}
diff --git a/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLWorker.java b/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLWorker.java
index 08a08136cfca9149d8328fdc87b32b60e71efb09..cfd80cd0349c3c95d69cecf3a0240c56ce9c4d18 100644
--- a/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLWorker.java
+++ b/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLWorker.java
@@ -23,32 +23,57 @@
 package net.jami.jams.ca.workers.crl;
 
 import lombok.Getter;
+import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
 import net.jami.jams.ca.JamsCA;
 import net.jami.jams.ca.workers.X509Worker;
 import net.jami.jams.common.objects.requests.RevocationRequest;
+import net.jami.jams.common.serialization.fs.FileStorage;
 import org.bouncycastle.asn1.x500.X500Name;
 import org.bouncycastle.asn1.x509.CRLReason;
 import org.bouncycastle.cert.X509CRLHolder;
 import org.bouncycastle.cert.X509v2CRLBuilder;
 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
 
+import java.io.File;
+import java.io.SyncFailedException;
 import java.security.PrivateKey;
 import java.security.cert.X509Certificate;
 import java.util.Date;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
 @Slf4j
 public class CRLWorker extends X509Worker<RevocationRequest> {
 
     @Getter
-    private AtomicReference<X509CRLHolder> existingCRL = null;
+    private final AtomicReference<X509CRLHolder> existingCRL = new AtomicReference<>();
+
+    @Getter
+    private final CRLFileStorage crlFileStorage = new CRLFileStorage(System.getProperty("user.dir") + File.separator + "crl.pem");
+
+    @Getter @Setter
+    private AtomicBoolean stop = new AtomicBoolean(false);
 
     public CRLWorker(PrivateKey privateKey, X509Certificate certificate) {
         super(privateKey, certificate);
+        try{
+            existingCRL.set(crlFileStorage.getData());
+        }
+        catch (Exception e){
+            log.warn("Could not find existing CRL file, if this is the first" +
+                " time you are starting the server or no CRL existed, this is fine");
+            X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(new X500Name((getCertificate()).getSubjectDN().getName()), new Date());
+            try {
+                existingCRL.set(crlBuilder.build(new JcaContentSignerBuilder("SHA512WITHRSA").setProvider("BC").build(getSigningKey())));
+                crlFileStorage.storeData(existingCRL.get());
+            }
+            catch (Exception e1){
+                log.error("Could not create blank CRL!");
+            }
+        }
         this.setDaemon(true);
         this.start();
-        //TODO: The CRL needs to be loaded from memory
         log.info("Instantiated & started a CRL Worker...");
     }
 
@@ -59,11 +84,18 @@ public class CRLWorker extends X509Worker<RevocationRequest> {
             if(revocationRequest != null) {
                 crlBuilder.addCRLEntry(revocationRequest.getIdentifier(), new Date(), CRLReason.privilegeWithdrawn);
             }
-            if (existingCRL != null){
-                crlBuilder.addCRL(existingCRL.get());
-            }
-            else existingCRL = new AtomicReference<>();
+            crlBuilder.addCRL(existingCRL.get());
             existingCRL.set(crlBuilder.build(new JcaContentSignerBuilder("SHA512WITHRSA").setProvider("BC").build(getSigningKey())));
+            boolean failedWrite = true;
+            while(failedWrite){
+                try{
+                    crlFileStorage.storeData(existingCRL.get());
+                    failedWrite = false;
+                }
+                catch (Exception e){
+                    log.warn("Failed to write file, trying again!");
+                }
+            }
             log.info("Successfully ran revocation routine");
         }
         catch (Exception e){
@@ -74,7 +106,7 @@ public class CRLWorker extends X509Worker<RevocationRequest> {
     @Override
     public void run() {
         boolean needsRefresh = false;
-        while(true){
+        while(!stop.get()){
             try{
                 while(getInput().isEmpty()){
                     if(needsRefresh){
@@ -97,5 +129,6 @@ public class CRLWorker extends X509Worker<RevocationRequest> {
                 log.error("An error has occured in the CRL signing thread: " + e.toString());
             }
         }
+        log.info("Stopped CRL Worker Thread...");
     }
 }
diff --git a/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilderTest.java b/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilderTest.java
index 6c8e6fa856fea1a7e47c23c242b9d31795b7dc2f..2a3f77f158216a659f88916b9be87255c69297d1 100644
--- a/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilderTest.java
+++ b/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilderTest.java
@@ -110,7 +110,7 @@ class SystemAccountBuilderTest {
 
 
         JamsCA jamsCA = new JamsCA();
-        jamsCA.init(JsonStream.serialize(config),caAccount,null);
+        jamsCA.init(JsonStream.serialize(config),caAccount,caAccount);
         RevocationRequest revocationRequest = new RevocationRequest();
         revocationRequest.setIdentifier(new BigInteger("91828882"));
         revocationRequest.setRevocationType(RevocationType.USER);
@@ -119,7 +119,7 @@ class SystemAccountBuilderTest {
             this.wait(2_000);
         }
         Assertions.assertNotNull(jamsCA.getLatestCRL());
-        Assertions.assertEquals(jamsCA.getLatestCRL().get().getRevokedCertificates().toArray().length,1,"Expected only 1 certificate!");
+        Assertions.assertEquals(1,jamsCA.getLatestCRL().get().getRevokedCertificates().toArray().length,"Expected only 1 certificate!");
 
         revocationRequest = new RevocationRequest();
         revocationRequest.setIdentifier(new BigInteger("17262653"));
@@ -129,9 +129,6 @@ class SystemAccountBuilderTest {
             this.wait(2_000);
         }
         Assertions.assertNotNull(jamsCA.getLatestCRL());
-        Assertions.assertEquals(jamsCA.getLatestCRL().get().getRevokedCertificates().toArray().length,2,"Expected only 2 certificates!");
-
-
-
+        Assertions.assertEquals(2,jamsCA.getLatestCRL().get().getRevokedCertificates().toArray().length,"Expected only 2 certificates!");
     }
 }
\ No newline at end of file
diff --git a/jams-common/pom.xml b/jams-common/pom.xml
index 065b4c7495ea8df8fa4e347d69376cf681f860ff..898d75355a6fdd576ed77935afd8b9be131c91a6 100644
--- a/jams-common/pom.xml
+++ b/jams-common/pom.xml
@@ -27,6 +27,11 @@
             <artifactId>xbean-classloader</artifactId>
             <version>${xbean.version}</version>
         </dependency>
+        <dependency>
+            <groupId>com.googlecode.ez-vcard</groupId>
+            <artifactId>ez-vcard</artifactId>
+            <version>${ez.vcard.version}</version>
+        </dependency>
     </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/jams-common/src/main/java/net/jami/jams/common/authmodule/AuthenticationModule.java b/jams-common/src/main/java/net/jami/jams/common/authmodule/AuthenticationModule.java
index ef212f879ac504652b8470a6ae61ffd4c90a56ca..1ec1d9eb75e447c678aa65007a3e2e25bbd0f5dc 100644
--- a/jams-common/src/main/java/net/jami/jams/common/authmodule/AuthenticationModule.java
+++ b/jams-common/src/main/java/net/jami/jams/common/authmodule/AuthenticationModule.java
@@ -26,6 +26,7 @@ import net.jami.jams.common.authentication.AuthenticationSource;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
 import net.jami.jams.common.jami.NameServer;
 import net.jami.jams.common.objects.user.User;
+import org.bouncycastle.cert.X509CRLHolder;
 
 import java.security.cert.X509Certificate;
 import java.security.interfaces.RSAPublicKey;
@@ -35,7 +36,7 @@ public interface AuthenticationModule {
 
     void attachAuthSource(AuthenticationSourceType type, String settings);
     AuthTokenResponse authenticateUser(String username, String password);
-    AuthTokenResponse authenticateUser(X509Certificate[] certificates);
+    AuthTokenResponse authenticateUser(X509Certificate[] certificates, X509CRLHolder crl, X509Certificate ca);
     ConcurrentHashMap<AuthModuleKey, AuthenticationSource> getAuthSources();
     boolean testModuleConfiguration(AuthenticationSourceType type, String configuration);
     boolean createUser(AuthenticationSourceType type, String realm, NameServer nameServer, User user);
diff --git a/jams-common/src/main/java/net/jami/jams/common/cryptoengineapi/CertificateAuthority.java b/jams-common/src/main/java/net/jami/jams/common/cryptoengineapi/CertificateAuthority.java
index 8ea454b8b691dc01ae1393ccf7892e54f5d6ea31..0d740e9477c577366d7cc5d5dc68f7f488de058a 100644
--- a/jams-common/src/main/java/net/jami/jams/common/cryptoengineapi/CertificateAuthority.java
+++ b/jams-common/src/main/java/net/jami/jams/common/cryptoengineapi/CertificateAuthority.java
@@ -44,5 +44,6 @@ public interface CertificateAuthority {
     String getLatestCRLPEMEncoded();
     OCSPResp getOCSPResponse(OCSPReq ocspRequest);
     X509Certificate getCA();
+    boolean shutdownThreads();
 
 }
diff --git a/jams-common/src/main/java/net/jami/jams/common/dao/DeleteStatementBuilder.java b/jams-common/src/main/java/net/jami/jams/common/dao/DeleteStatementBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..46be13b6a5b031d20aff0b0d66ca9f6800a72e9d
--- /dev/null
+++ b/jams-common/src/main/java/net/jami/jams/common/dao/DeleteStatementBuilder.java
@@ -0,0 +1,61 @@
+/*
+* Copyright (C) 2020 by Savoir-faire Linux
+* Authors: William Enright <william.enright@savoirfairelinux.com>
+*          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
+*          Johnny Flores <johnny.flores@savoirfairelinux.com>
+*          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
+*          Felix Sidokhine <felix.sidokhine@savoirfairelinux.com>
+*
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+package net.jami.jams.common.dao;
+
+import net.jami.jams.common.dao.connectivity.SQLConnection;
+
+import java.sql.PreparedStatement;
+
+public class DeleteStatementBuilder {
+
+    public static PreparedStatement buildStatement(String table, StatementList statementElements,
+                                                   SQLConnection connection) throws Exception {
+        PreparedStatement ps = null;
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("DELETE FROM ").append(table);
+        if(statementElements != null) {
+            stringBuilder.append(" WHERE ");
+            for (StatementElement statementElement : statementElements.getStatements()) {
+                stringBuilder
+                    .append(statementElement.getColumn())
+                    .append(" ")
+                    .append(statementElement.getOperator())
+                    .append(" ")
+                    .append("?")
+                    .append(" ")
+                    .append(statementElement.getNextStatementRelation())
+                    .append(" ");
+            }
+            ps = connection.getConnection().prepareStatement(stringBuilder.toString());
+            int i = 1;
+            for (StatementElement statementElement : statementElements.getStatements()) {
+                ps.setString(i, statementElement.getValue());
+                i++;
+            }
+        }
+        else{
+            ps = connection.getConnection().prepareStatement(stringBuilder.toString());
+        }
+        return ps;
+    }
+}
diff --git a/jams-common/src/main/java/net/jami/jams/common/dao/SelectStatementBuilder.java b/jams-common/src/main/java/net/jami/jams/common/dao/SelectStatementBuilder.java
index c361e884579819fca538de04fdcedd2c33db2396..fb80dea462edd8424084d87e789879667fd13757 100644
--- a/jams-common/src/main/java/net/jami/jams/common/dao/SelectStatementBuilder.java
+++ b/jams-common/src/main/java/net/jami/jams/common/dao/SelectStatementBuilder.java
@@ -44,7 +44,8 @@ public class SelectStatementBuilder {
                         .append(" ")
                         .append("?")
                         .append(" ")
-                        .append(statementElement.getNextStatementRelation());
+                        .append(statementElement.getNextStatementRelation())
+                        .append(" ");
             }
             ps = connection.getConnection().prepareStatement(stringBuilder.toString());
             int i = 1;
diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/contacts/Contact.java b/jams-common/src/main/java/net/jami/jams/common/objects/contacts/Contact.java
index 2804fd9605299b4dbd70e598aaf4c8e4388388a2..dfcf11b391b0b0dcc43ead99a63f88183f40affa 100644
--- a/jams-common/src/main/java/net/jami/jams/common/objects/contacts/Contact.java
+++ b/jams-common/src/main/java/net/jami/jams/common/objects/contacts/Contact.java
@@ -22,10 +22,46 @@
 */
 package net.jami.jams.common.objects.contacts;
 
+import com.jsoniter.annotation.JsonIgnore;
 import lombok.Getter;
+import lombok.NoArgsConstructor;
 import lombok.Setter;
+import net.jami.jams.common.serialization.database.DatabaseObject;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 
 @Getter
 @Setter
-public class Contact {
+@NoArgsConstructor
+public class Contact implements DatabaseObject {
+
+    @JsonIgnore //Ignore the owner because he is irrelevant.
+    private String owner;
+    private String uri;
+    private String displayName;
+
+    public Contact(ResultSet rs) throws Exception {
+        this.owner = rs.getString("owner");
+        this.uri = rs.getString("uri");
+        this.displayName = rs.getString("displayName");
+    }
+
+    @Override
+    public PreparedStatement getInsert(PreparedStatement ps) throws Exception {
+        ps.setString(1,owner);
+        ps.setString(2,uri);
+        ps.setString(3,displayName);
+        return ps;
+    }
+
+    @Override
+    public PreparedStatement getDelete(PreparedStatement ps) throws Exception {
+        return null;
+    }
+
+    @Override
+    public PreparedStatement getUpdate(PreparedStatement ps) throws Exception {
+        return null;
+    }
 }
diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/user/UserProfile.java b/jams-common/src/main/java/net/jami/jams/common/objects/user/UserProfile.java
index 96e6c856a05993ffb2b8fe97bff58aa7bb6e69f6..718a4ab9ce890d11b1393996c069f81083fecdc9 100644
--- a/jams-common/src/main/java/net/jami/jams/common/objects/user/UserProfile.java
+++ b/jams-common/src/main/java/net/jami/jams/common/objects/user/UserProfile.java
@@ -22,10 +22,24 @@
 */
 package net.jami.jams.common.objects.user;
 
+import com.jsoniter.annotation.JsonIgnore;
+import ezvcard.Ezvcard;
+import ezvcard.VCard;
+import ezvcard.VCardVersion;
+import ezvcard.parameter.EmailType;
+import ezvcard.parameter.ImageType;
+import ezvcard.parameter.TelephoneType;
+import ezvcard.property.Organization;
+import ezvcard.property.Photo;
+import ezvcard.property.StructuredName;
+import ezvcard.property.Telephone;
 import lombok.Getter;
 import lombok.Setter;
+import org.bouncycastle.util.encoders.Base64;
 
 import java.lang.reflect.Method;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 
 @Getter
@@ -52,5 +66,30 @@ public class UserProfile {
     private String email;
     private String organization;
 
+    @JsonIgnore
+    //Ignore this if we pass through JSON iterator.
+    public String getAsVCard(){
+        VCard vCard = new VCard();
+
+        //We assume these always exist...
+        StructuredName structuredName = new StructuredName();
+        structuredName.setFamily(URLEncoder.encode(this.getLastName(), StandardCharsets.UTF_8));
+        structuredName.setGiven(URLEncoder.encode(this.getFirstName(), StandardCharsets.UTF_8));
+        vCard.setStructuredName(structuredName);
+
+        if(this.getPhoneNumber() != null) vCard.addTelephoneNumber(this.getPhoneNumber(), TelephoneType.WORK);
+        if(this.getMobileNumber() != null) vCard.addTelephoneNumber(this.getMobileNumber(),TelephoneType.CELL);
+        if(this.getFaxNumber() != null) vCard.addTelephoneNumber(this.getFaxNumber(), TelephoneType.FAX);
+        if(this.getEmail() != null) vCard.addEmail(this.getEmail(), EmailType.WORK);
+        if(this.getOrganization() != null) vCard.setOrganization(this.getOrganization());
+
+        /*I think this is how Base64 will work in this case*/
+        if(this.getProfilePicture() != null) {
+            Photo photo = new Photo(Base64.decode(this.getProfilePicture()), ImageType.JPEG);
+            vCard.addPhoto(photo);
+        }
+
+        return Ezvcard.write(vCard).version(VCardVersion.V3_0).go();
+    }
 
 }
diff --git a/jams-common/src/main/java/net/jami/jams/common/serialization/database/DatabaseObject.java b/jams-common/src/main/java/net/jami/jams/common/serialization/database/DatabaseObject.java
index 2198d8cac27346ea957e9460e74004d02eedf541..0489430e839adb39190231da637a55253987d813 100644
--- a/jams-common/src/main/java/net/jami/jams/common/serialization/database/DatabaseObject.java
+++ b/jams-common/src/main/java/net/jami/jams/common/serialization/database/DatabaseObject.java
@@ -25,7 +25,6 @@ package net.jami.jams.common.serialization.database;
 import java.sql.PreparedStatement;
 
 public interface DatabaseObject {
-
     PreparedStatement getInsert(PreparedStatement ps) throws Exception;
     PreparedStatement getDelete(PreparedStatement ps) throws Exception;
     PreparedStatement getUpdate(PreparedStatement ps) throws Exception;
diff --git a/jams-common/src/main/java/net/jami/jams/common/serialization/fs/FileStorage.java b/jams-common/src/main/java/net/jami/jams/common/serialization/fs/FileStorage.java
new file mode 100644
index 0000000000000000000000000000000000000000..43322d32d568e86edad07a8691c339d11e4cfc05
--- /dev/null
+++ b/jams-common/src/main/java/net/jami/jams/common/serialization/fs/FileStorage.java
@@ -0,0 +1,64 @@
+/*
+* Copyright (C) 2020 by Savoir-faire Linux
+* Authors: William Enright <william.enright@savoirfairelinux.com>
+*          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
+*          Johnny Flores <johnny.flores@savoirfairelinux.com>
+*          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
+*          Felix Sidokhine <felix.sidokhine@savoirfairelinux.com>
+*
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+package net.jami.jams.common.serialization.fs;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+@Getter
+@Setter
+public abstract class FileStorage<T> {
+
+    private File file;
+    private FileInputStream fileInputStream;
+    private FileOutputStream fileOutputStream;
+    private FileDescriptor fileDescriptor;
+
+    public FileStorage(String file) {
+        this.file = new File(file);
+    }
+
+    public abstract T getObject(byte[] bytes) throws Exception;
+    public abstract byte[] getBytesFromObject(T object) throws Exception;
+
+    public T getData() throws Exception{
+        fileInputStream = new FileInputStream(file);
+        return getObject(fileInputStream.readAllBytes());
+    }
+
+    public void storeData(T data) throws Exception{
+        fileOutputStream = new FileOutputStream(file);
+        fileDescriptor = fileOutputStream.getFD();
+        fileOutputStream.write(getBytesFromObject(data));
+        fileOutputStream.flush();
+        fileDescriptor.sync();
+    }
+
+
+
+}
diff --git a/jams-launcher/src/main/java/launcher/AppStarter.java b/jams-launcher/src/main/java/launcher/AppStarter.java
index d19d7dd1f502cea4b87c64740143b68ac9fccdf6..5fe3d848fa7edd9a49dda7700e5dc1fe5eec351f 100644
--- a/jams-launcher/src/main/java/launcher/AppStarter.java
+++ b/jams-launcher/src/main/java/launcher/AppStarter.java
@@ -41,9 +41,9 @@ public class AppStarter extends Thread {
     private final AtomicBoolean doUpdate = new AtomicBoolean(false);
     private Server server;
     private AppUpdater appUpdater;
-    private static Integer port;
-    private static String serverCertificate;
-    private static String serverPrivateKey;
+    private static Integer port = 8080;
+    private static String serverCertificate = null;
+    private static String serverPrivateKey = null;
 
 
     /**
diff --git a/jams-server/pom.xml b/jams-server/pom.xml
index 16d4bc93a882176e56580aec0eaf03f8167df009..279ea341417a2c2a29a674371fd49d8f9db0741e 100644
--- a/jams-server/pom.xml
+++ b/jams-server/pom.xml
@@ -15,7 +15,6 @@
             <groupId>net.jami</groupId>
             <artifactId>cryptoengine</artifactId>
             <version>${revision}</version>
-            <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.tomcat.embed</groupId>
@@ -36,25 +35,21 @@
             <groupId>net.jami</groupId>
             <artifactId>datastore</artifactId>
             <version>${revision}</version>
-            <scope>compile</scope>
         </dependency>
         <dependency>
-            <groupId>javax.servlet</groupId>
-            <artifactId>javax.servlet-api</artifactId>
-            <version>${javax.servlet.version}</version>
-            <scope>provided</scope>
+            <groupId>net.jami</groupId>
+            <artifactId>jams-common</artifactId>
+            <version>${revision}</version>
         </dependency>
         <dependency>
             <groupId>net.jami</groupId>
             <artifactId>jami-nameserver</artifactId>
             <version>${revision}</version>
-            <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>net.jami</groupId>
             <artifactId>jami-dht</artifactId>
             <version>${revision}</version>
-            <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>com.nimbusds</groupId>
diff --git a/jams-server/src/main/java/net/jami/jams/server/Server.java b/jams-server/src/main/java/net/jami/jams/server/Server.java
index 536f915d9de8503fe9628eabff4c31edb9de5b37..da45b671db4329763655cf310f96f205e57883a7 100644
--- a/jams-server/src/main/java/net/jami/jams/server/Server.java
+++ b/jams-server/src/main/java/net/jami/jams/server/Server.java
@@ -23,6 +23,7 @@
 package net.jami.jams.server;
 
 import com.jsoniter.JsonIterator;
+import javassist.ClassPool;
 import lombok.extern.slf4j.Slf4j;
 import net.jami.datastore.main.DataStore;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
@@ -48,16 +49,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
 
 @Slf4j
 //In order to make this "stoppable" to simply, I turned the server itself into a thread.
-//The reasoning: the main two problems
 public class Server {
 
     public final static AtomicBoolean isInstalled = new AtomicBoolean(false);
     public final static AtomicBoolean activated = new AtomicBoolean(false);
 
-    static {
-        JsoniterRegistry.initCodecs();
-    }
-
     public static DataStore dataStore;
     //This one gets loaded via JAR, to make it more flexible.
     public static CertificateAuthority certificateAuthority;
@@ -68,21 +64,17 @@ public class Server {
     public static AppUpdater appUpdater;
 
     public Server(AppUpdater appUpdater, String port, String serverCertificate, String serverPrivateKey) {
+        JsoniterRegistry.initCodecs();
         Server.appUpdater = appUpdater;
-
         String[] args = {port, serverCertificate, serverPrivateKey};
-
-        if ((args.length > 0)) main(args);
-        else main(new String[]{});
+        main(args);
     }
 
 
     public static void main(String[] args) {
-        //Start tomcat.
+        //This is a fix to drop old cached stuff from the tomcat classloader.
+        ClassPool.getDefault().clearImportedPackages();
         switch (args.length) {
-            case 0:
-                tomcatLauncher = new TomcatLauncher(8080);
-                break;
             case 1:
                 tomcatLauncher = new TomcatLauncher(Integer.parseInt(args[0]));
                 break;
diff --git a/jams-server/src/main/java/net/jami/jams/server/core/TomcatConnectorFactory.java b/jams-server/src/main/java/net/jami/jams/server/core/TomcatConnectorFactory.java
index cb661365fe81fc312491486c671d83cf0c543586..68198f8ba993a1aedb2f4ec54c8701f3cd2ccf58 100644
--- a/jams-server/src/main/java/net/jami/jams/server/core/TomcatConnectorFactory.java
+++ b/jams-server/src/main/java/net/jami/jams/server/core/TomcatConnectorFactory.java
@@ -24,6 +24,8 @@ package net.jami.jams.server.core;
 
 import lombok.extern.slf4j.Slf4j;
 import org.apache.catalina.connector.Connector;
+import org.apache.tomcat.util.net.SSLHostConfig;
+import org.apache.tomcat.util.net.SSLHostConfigCertificate;
 
 import java.io.File;
 
@@ -33,25 +35,26 @@ public class TomcatConnectorFactory {
     public static Connector getSSLConnectorWithTrustStore(String certificateFile, String keyFile, int port) {
         log.info(System.getProperty("user.dir") + File.separator + "keystore.jks");
         Connector connector = getSSLConnectorWithoutTrustStore(certificateFile, keyFile, port);
-        connector.setAttribute("truststoreFile", System.getProperty("user.dir") + File.separator + "keystore.jks");
-        connector.setAttribute("clientAuth", "optional");
-        connector.setAttribute("truststorePassword", "changeit");
+        connector.findSslHostConfigs()[0].setTruststoreFile(System.getProperty("user.dir") + File.separator + "keystore.jks");
+        connector.findSslHostConfigs()[0].setTruststorePassword("changeit");
+        connector.findSslHostConfigs()[0].setCertificateVerification("optional");
         return connector;
     }
 
     public static Connector getSSLConnectorWithoutTrustStore(String certificateFile, String keyFile, int port) {
         //Check if trust store exists or create it if necessary.
         Connector connector = new Connector();
+        SSLHostConfig sslConfig = new SSLHostConfig();
+        SSLHostConfigCertificate sslHostConfigCertificate = new SSLHostConfigCertificate(sslConfig, SSLHostConfigCertificate.Type.RSA);
+        sslHostConfigCertificate.setCertificateFile(System.getProperty("user.dir") + File.separator + certificateFile);
+        sslHostConfigCertificate.setCertificateKeyFile(System.getProperty("user.dir") + File.separator + keyFile);
+        sslConfig.addCertificate(sslHostConfigCertificate);
+        sslConfig.setProtocols("TLSv1.3");
+        connector.addSslHostConfig(sslConfig);
         connector.setPort(port);
         connector.setSecure(true);
         connector.setScheme("https");
-        connector.setAttribute("protocol", "org.apache.coyote.http11.Http11AprProtocol");
-        connector.setAttribute("SSLCertificateFile", System.getProperty("user.dir") + File.separator + certificateFile);
-        connector.setAttribute("SSLCertificateKeyFile", System.getProperty("user.dir") + File.separator + keyFile);
-        connector.setAttribute("protocol", "HTTP/1.1");
-        connector.setAttribute("sslProtocol", "TLS");
-        connector.setAttribute("maxThreads", "200");
-        connector.setAttribute("SSLEnabled", true);
+        connector.setProperty("SSLEnabled", "true");
         return connector;
     }
 
@@ -60,9 +63,6 @@ public class TomcatConnectorFactory {
         Connector connector = new Connector();
         connector.setPort(port);
         connector.setScheme("http");
-        connector.setAttribute("protocol", "org.apache.coyote.http11.Http11NioProtocol");
-        connector.setAttribute("protocol", "HTTP/1.1");
-        connector.setAttribute("maxThreads", "200");
         return connector;
     }
 
diff --git a/jams-server/src/main/java/net/jami/jams/server/core/TomcatLauncher.java b/jams-server/src/main/java/net/jami/jams/server/core/TomcatLauncher.java
index 814a9658155dba0b3b700873d995c33e761e7fda..7fcf7b2e1d2699d6f28edd50a8ddb46b3a70ca96 100644
--- a/jams-server/src/main/java/net/jami/jams/server/core/TomcatLauncher.java
+++ b/jams-server/src/main/java/net/jami/jams/server/core/TomcatLauncher.java
@@ -1,29 +1,29 @@
 /*
-* Copyright (C) 2020 by Savoir-faire Linux
-* Authors: William Enright <william.enright@savoirfairelinux.com>
-*          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
-*          Johnny Flores <johnny.flores@savoirfairelinux.com>
-*          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
-*          Felix Sidokhine <felix.sidokhine@savoirfairelinux.com>
-*
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 3 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program.  If not, see <https://www.gnu.org/licenses/>.
-*/
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Authors: William Enright <william.enright@savoirfairelinux.com>
+ *          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
+ *          Johnny Flores <johnny.flores@savoirfairelinux.com>
+ *          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
+ *          Felix Sidokhine <felix.sidokhine@savoirfairelinux.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
 package net.jami.jams.server.core;
 
 import lombok.extern.slf4j.Slf4j;
-import net.jami.jams.server.Server;
 import org.apache.catalina.WebResourceRoot;
 import org.apache.catalina.connector.Connector;
 import org.apache.catalina.core.StandardContext;
@@ -36,20 +36,18 @@ import org.apache.tomcat.util.descriptor.web.ErrorPage;
 import java.awt.*;
 import java.io.File;
 import java.net.URI;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 
+import static net.jami.jams.server.Server.certificateAuthority;
 
 //This class boots the tomcat server which provides the subsystem
 //for the API calls.
 @Slf4j
 public class TomcatLauncher {
 
-    private Tomcat tomcat = new Tomcat();
-    private static Connector connector;
-    private static StandardContext context;
+    private final Tomcat tomcat = new Tomcat();
+    private StandardContext context;
 
     public TomcatLauncher(int port) {
         tomcat.getService().addConnector(TomcatConnectorFactory.getNoSSLConnector(port));
@@ -57,18 +55,23 @@ public class TomcatLauncher {
     }
 
     public TomcatLauncher(int port, String certificateFile, String keyFile) {
-        if(Files.exists(Paths.get(System.getProperty("user.dir") + File.separator + "keystore.jks"))){
+        if (!Files.exists(Paths.get(System.getProperty("user.dir") + File.separator + certificateFile)) ||
+            !Files.exists(Paths.get(System.getProperty("user.dir") + File.separator + keyFile))) {
+            log.info("Could not find certificate or keyfile, starting in plain HTTP connector as fallback!");
+            tomcat.getService().addConnector(TomcatConnectorFactory.getNoSSLConnector(port));
+            this.startServer();
+            return;
+        }
+        if (Files.exists(Paths.get(System.getProperty("user.dir") + File.separator + "keystore.jks"))) {
             log.info("Found a valid trust store, injecting into tomcat!");
             tomcat.getService().addConnector(TomcatConnectorFactory.getSSLConnectorWithTrustStore(certificateFile, keyFile, port));
-        }
-        else{
-            connector = TomcatConnectorFactory.getSSLConnectorWithoutTrustStore(certificateFile, keyFile, port);
+        } else {
+            Connector connector = TomcatConnectorFactory.getSSLConnectorWithoutTrustStore(certificateFile, keyFile, port);
             tomcat.getService().addConnector(connector);
         }
         this.startServer();
     }
 
-
     public void startServer() {
         String jarName = System.getProperty("user.dir") + File.separator + "jams-server.jar";
         log.info("JAR Resource File = " + jarName);
@@ -80,12 +83,11 @@ public class TomcatLauncher {
         if (jarName.contains(".jar")) {
             resources.addPreResources(new JarResourceSet(resources, "/WEB-INF/classes", jarName, "/net/jami/jams/server/servlets"));
             resources.addPreResources(new JarResourceSet(resources, "/", jarName, "/webapp"));
-        }
-        else {
+        } else {
             log.info("WARNING: You are running from your local filesystem, this makes sense only for developers!");
             StringBuilder basePath = new StringBuilder();
             String[] paths = System.getProperty("user.dir").split("/");
-            for(int i=0; i < paths.length-1; i++){
+            for (int i = 0; i < paths.length - 1; i++) {
                 basePath.append("/").append(paths[i]);
             }
             basePath.append("/jams-server");
@@ -99,28 +101,29 @@ public class TomcatLauncher {
         errorPage.setErrorCode(404);
         errorPage.setLocation("/index");
         context.addErrorPage(errorPage);
-        try{
+        try {
             tomcat.start();
             //Try to pop-up Web-UI
-            if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE))
-                Desktop.getDesktop().browse(new URI("https://localhost:8080"));
-            else
+            if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
+                Desktop.getDesktop().browse(new URI(tomcat.getConnector().getScheme() + "://localhost:8080"));
+            } else {
                 log.info("There is no graphical interface on this system - please connect remotely!");
-
+            }
         } catch (Exception e) {
             log.error("Could not start web-server!");
         }
     }
 
-    public void stopTomcat(){
+    public void stopTomcat() {
         try {
             synchronized (tomcat) {
+                certificateAuthority.shutdownThreads();
                 tomcat.stop();
+                context.destroy();
                 tomcat.destroy();
             }
-        }
-        catch (Exception e){
-            log.info("Failed to stop tomcat server with error {}",e.getMessage());
+        } catch (Exception e) {
+            log.info("Failed to stop tomcat server with error {}", e.getMessage());
         }
     }
 }
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DeviceServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DeviceServlet.java
index 839c8f48011ab43f056b94fa62708ffe9452c8e7..ef068abbecc5a2f36db70cb26fa3c114c7d48a39 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DeviceServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DeviceServlet.java
@@ -23,16 +23,16 @@
 package net.jami.jams.server.servlets.api.admin.devices;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.dao.StatementElement;
 import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.responses.DeviceRevocationResponse;
 import net.jami.jams.server.core.workflows.RevokeDeviceFlow;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.dataStore;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DevicesServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DevicesServlet.java
index 33302d22b1434fe7bca05cf7803b62b91aeb9fad..05dca7927ea98d71bcff42f3a147a89e07b5043d 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DevicesServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/devices/DevicesServlet.java
@@ -23,14 +23,14 @@
 package net.jami.jams.server.servlets.api.admin.devices;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.dao.StatementElement;
 import net.jami.jams.common.dao.StatementList;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.dataStore;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/directory/DirectoryEntryServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/directory/DirectoryEntryServlet.java
index 450396d97b5d69bf53602232f21645918017195e..357293515cd91dc470e1df959a12b243708e5557 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/directory/DirectoryEntryServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/directory/DirectoryEntryServlet.java
@@ -23,16 +23,16 @@
 package net.jami.jams.server.servlets.api.admin.directory;
 
 import com.jsoniter.JsonIterator;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.extern.slf4j.Slf4j;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
 import net.jami.jams.common.authmodule.AuthModuleKey;
 import net.jami.jams.common.objects.user.UserProfile;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.userAuthenticationModule;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/update/SubscriptionServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/update/SubscriptionServlet.java
index 4607ccf3ba477c6e5c57711bde8b64bde18c7edc..f2b48ab0c4394be7ef09dfa449596b3adbf244ab 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/update/SubscriptionServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/update/SubscriptionServlet.java
@@ -23,15 +23,15 @@
 package net.jami.jams.server.servlets.api.admin.update;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.ca.JamsCA;
 import net.jami.jams.common.objects.responses.SubscriptionStatusResponse;
 import net.jami.jams.server.Server;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 @WebServlet("/api/subscription")
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/update/UpdateServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/update/UpdateServlet.java
index c35b93aa4948fb2c5892fd69ac76ba43460e412f..08785810da8620c18b10afc7416f1a65a2c5ee92 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/update/UpdateServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/update/UpdateServlet.java
@@ -23,13 +23,13 @@
 package net.jami.jams.server.servlets.api.admin.update;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.updater.FullSystemStatusResponse;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.appUpdater;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserServlet.java
index 153dde6c93265dbd8afc1c590919afdfb8d6f122..2128e21e56ea1d835a472d7eb9cfe072c0951c05 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UserServlet.java
@@ -23,6 +23,11 @@
 package net.jami.jams.server.servlets.api.admin.users;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
 import net.jami.jams.common.dao.StatementElement;
 import net.jami.jams.common.dao.StatementList;
@@ -30,11 +35,6 @@ import net.jami.jams.common.objects.responses.DeviceRevocationResponse;
 import net.jami.jams.common.objects.user.User;
 import net.jami.jams.server.core.workflows.RevokeUserFlow;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.dataStore;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UsersServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UsersServlet.java
index 9e0f381543c3b72acec07c46c6c703f3368cd2c2..d0ba9762ae8ed335b0db6c1abdd6f293c44d5a29 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UsersServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/admin/users/UsersServlet.java
@@ -23,12 +23,12 @@
 package net.jami.jams.server.servlets.api.admin.users;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.dataStore;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/contacts/ContactServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/contacts/ContactServlet.java
index 9b0626fde9b5bb026e0ac1caa672ac7128dfb703..af88afea4c3e045e90d5a7b442fda15c467deeac 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/contacts/ContactServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/contacts/ContactServlet.java
@@ -22,28 +22,48 @@
 */
 package net.jami.jams.server.servlets.api.auth.contacts;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import com.jsoniter.JsonIterator;
+import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import net.jami.jams.common.dao.StatementElement;
+import net.jami.jams.common.dao.StatementList;
+import net.jami.jams.common.objects.contacts.Contact;
+
 import java.io.IOException;
+import java.util.List;
+
+import static net.jami.jams.server.Server.dataStore;
 
 @WebServlet("/api/auth/contacts")
 public class ContactServlet extends HttpServlet {
 
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        super.doGet(req, resp);
+        StatementList statementList = new StatementList();
+        statementList.addStatement(new StatementElement("owner","=",req.getAttribute("username").toString(),""));
+        List<Contact> contactList = dataStore.getContactDao().getObjects(statementList);
+        resp.getOutputStream().write(JsonStream.serialize(contactList).getBytes());
     }
 
     @Override
     protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        super.doPut(req, resp);
+        Contact contact = JsonIterator.deserialize(req.getInputStream().readAllBytes(),Contact.class);
+        contact.setOwner(req.getAttribute("username").toString());
+        if(dataStore.getContactDao().storeObject(contact)) resp.setStatus(200);
+        else resp.sendError(500,"Could not store contact!");
     }
 
+    //TODO: Because deleting requires sending the URI in the body, didn't want to do this now.
     @Override
     protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        super.doDelete(req, resp);
+        StatementList statementList = new StatementList();
+        statementList.addStatement(new StatementElement("owner","=",req.getAttribute("username").toString(),"AND"));
+        statementList.addStatement(new StatementElement("uri","=",req.getParameter("uri"),""));
+        if(dataStore.getContactDao().deleteObject(statementList)) resp.setStatus(200);
+        else resp.sendError(500,"Could not delete a contact!");
     }
 }
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DeviceServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DeviceServlet.java
index 55edeb816404674bdfd239b27cd0c072f38c8f71..18a3c81344769f92f7ab0090723aca91e15c3544 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DeviceServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DeviceServlet.java
@@ -24,6 +24,11 @@ package net.jami.jams.server.servlets.api.auth.device;
 
 import com.jsoniter.JsonIterator;
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.dao.StatementElement;
 import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.requests.DeviceRegistrationRequest;
@@ -32,11 +37,6 @@ import net.jami.jams.common.objects.responses.DeviceRevocationResponse;
 import net.jami.jams.server.core.workflows.RegisterDeviceFlow;
 import net.jami.jams.server.core.workflows.RevokeDeviceFlow;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.dataStore;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DevicesServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DevicesServlet.java
index f2f4798a945a5f5ce7e02db00746a4fda56a5988..8cc741e4e63e60853ad4570de5e6ca8265af8aff 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DevicesServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/device/DevicesServlet.java
@@ -23,14 +23,14 @@
 package net.jami.jams.server.servlets.api.auth.device;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.dao.StatementElement;
 import net.jami.jams.common.dao.StatementList;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.dataStore;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/DirectoriesServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/DirectoriesServlet.java
index d73b9b750e64f690fccf7883f13570cda07a03f4..7023837cb184c73c281e29ab849c9763b17f362e 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/DirectoriesServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/DirectoriesServlet.java
@@ -23,12 +23,12 @@
 package net.jami.jams.server.servlets.api.auth.directory;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.userAuthenticationModule;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/DirectoryEntryServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/DirectoryEntryServlet.java
index dcdc4c1e5f9de98750972d0530e550b8b5574c2f..5860c68396359db9e6dc9dd8315ba4548a27ed2d 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/DirectoryEntryServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/DirectoryEntryServlet.java
@@ -23,15 +23,15 @@
 package net.jami.jams.server.servlets.api.auth.directory;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
 import net.jami.jams.common.authmodule.AuthModuleKey;
 import net.jami.jams.common.objects.user.UserProfile;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -51,7 +51,10 @@ public class DirectoryEntryServlet extends HttpServlet {
             UserProfile[] profiles = userAuthenticationModule.getAuthSources()
                     .get(new AuthModuleKey(req.getParameter("directory"), AuthenticationSourceType.fromString(req.getParameter("directoryType"))))
                     .getUserProfile(req.getParameter("username"), "LOGON_NAME");
-            resp.getOutputStream().write(JsonStream.serialize(profiles[0]).getBytes());
+            if(req.getParameter("format").equals("vcard")){
+                resp.getOutputStream().write(profiles[0].getAsVCard().getBytes());
+            }
+            else resp.getOutputStream().write(JsonStream.serialize(profiles[0]).getBytes());
             return;
         }
         List<UserProfile> userProfiles = new ArrayList<>();
@@ -59,7 +62,10 @@ public class DirectoryEntryServlet extends HttpServlet {
             UserProfile[] profiles = v.getUserProfile(req.getParameter("username"), "LOGON_NAME");
             if (profiles != null && profiles.length != 0) userProfiles.addAll(Arrays.asList(profiles));
         });
-        resp.getOutputStream().write(JsonStream.serialize(userProfiles.get(0)).getBytes());
+        if(req.getParameter("format").equals("vcard")){
+            resp.getOutputStream().write(userProfiles.get(0).getAsVCard().getBytes());
+        }
+        else resp.getOutputStream().write(JsonStream.serialize(userProfiles.get(0)).getBytes());
     }
 
     @Override
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/SearchDirectoryServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/SearchDirectoryServlet.java
index 7dd3890f2f79614ce35be6d9cd431b03d9617baa..69e318c33e4f376173589eeb3759b6f975420969 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/SearchDirectoryServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/directory/SearchDirectoryServlet.java
@@ -23,13 +23,13 @@
 package net.jami.jams.server.servlets.api.auth.directory;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.objects.user.UserProfile;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/login/AuthRequestProcessor.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/login/AuthRequestProcessor.java
index 9084c090572da86d18a76cfb4b690a1925fba662..181bc0963ac41aab5bb96d115294b8defe01ee24 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/login/AuthRequestProcessor.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/login/AuthRequestProcessor.java
@@ -26,13 +26,15 @@ import net.jami.jams.common.authmodule.AuthTokenResponse;
 
 import java.security.cert.X509Certificate;
 
+import static net.jami.jams.server.Server.certificateAuthority;
 import static net.jami.jams.server.Server.userAuthenticationModule;
 
 public class AuthRequestProcessor {
 
     //This case does not talk to the authentication module, only to the ca
     public static AuthTokenResponse processX509Auth(X509Certificate[] certificates){
-        return userAuthenticationModule.authenticateUser(certificates);
+        return userAuthenticationModule.authenticateUser(certificates,certificateAuthority.getLatestCRL().get(),
+            certificateAuthority.getCA());
     }
 
     public static AuthTokenResponse processUsernamePasswordAuth(String username, String password){
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/login/LoginServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/login/LoginServlet.java
index 28dd97ae65b70ca9bae20517e26c748066f5da79..66d01c9fcee8f03247fcc6240090489eb7a3224d 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/login/LoginServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/login/LoginServlet.java
@@ -23,13 +23,13 @@
 package net.jami.jams.server.servlets.api.auth.login;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.authmodule.AuthTokenResponse;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.security.cert.X509Certificate;
 
@@ -53,8 +53,8 @@ public class LoginServlet extends HttpServlet {
             res = processUsernamePasswordAuth(req.getHeader("authorization"));
         }
         //Case 3 SSL Certificate
-        if(req.getAttribute("javax.servlet.request.X509Certificate") != null){
-            res = processX509Auth((X509Certificate[])req.getAttribute("javax.servlet.request.X509Certificate"));
+        if(req.getAttribute("jakarta.servlet.request.X509Certificate") != null){
+            res = processX509Auth((X509Certificate[])req.getAttribute("jakarta.servlet.request.X509Certificate"));
         }
         //Here we catch the need to create a user (this is only possible in 1 & 2).
         if(res == null) resp.sendError(403,"Invalid credentials!");
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/user/UserServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/user/UserServlet.java
index be06a27ea4a4719e57e38a633a13caad14ea7fea..48074551b14ed4e7b60fc8d7c35b9f2b80368048 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/user/UserServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/user/UserServlet.java
@@ -23,15 +23,15 @@
 package net.jami.jams.server.servlets.api.auth.user;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
 import net.jami.jams.common.dao.StatementElement;
 import net.jami.jams.common.dao.StatementList;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.dataStore;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateAuthSourceServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateAuthSourceServlet.java
index 1da2fa11c1d990a201b5719c25376224659017e3..d063766068bd6da27ac02c0fcf5f0b195167e91a 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateAuthSourceServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateAuthSourceServlet.java
@@ -24,19 +24,21 @@ package net.jami.jams.server.servlets.api.install;
 
 import com.jsoniter.JsonIterator;
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
 import net.jami.jams.common.objects.requests.CreateAuthSourceRequest;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.userAuthenticationModule;
 
 @WebServlet("/api/install/auth")
+@Slf4j
 public class CreateAuthSourceServlet extends HttpServlet {
 
     @Override
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateCAServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateCAServlet.java
index ebf1007b4565ef15c86d293b09731345b24165fd..b8c5486478a9db89f242c145cbf9c76599dc27dd 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateCAServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateCAServlet.java
@@ -23,14 +23,14 @@
 package net.jami.jams.server.servlets.api.install;
 
 import com.jsoniter.JsonIterator;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.objects.requests.CreateCARequest;
 import net.jami.jams.common.utils.Validator;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 @WebServlet("/api/install/ca")
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateServerSettingsServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateServerSettingsServlet.java
index 14a36c99cb309a4ba8ffe6f4988cc3c1d1d6a733..9c55af402669b67553d9173b67768828113ebf13 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateServerSettingsServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/CreateServerSettingsServlet.java
@@ -23,14 +23,14 @@
 package net.jami.jams.server.servlets.api.install;
 
 import com.jsoniter.JsonIterator;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.cryptoengineapi.CertificateAuthorityConfig;
 import net.jami.jams.server.core.workflows.InstallationFinalizer;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 @WebServlet("/api/install/settings")
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/InstallLastStepServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/InstallLastStepServlet.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe253da6a1ab512401f5a8b31ff247fc35854c1e
--- /dev/null
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/InstallLastStepServlet.java
@@ -0,0 +1,45 @@
+/*
+* Copyright (C) 2020 by Savoir-faire Linux
+* Authors: William Enright <william.enright@savoirfairelinux.com>
+*          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
+*          Johnny Flores <johnny.flores@savoirfairelinux.com>
+*          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
+*          Felix Sidokhine <felix.sidokhine@savoirfairelinux.com>
+*
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+package net.jami.jams.server.servlets.api.install;
+
+import com.jsoniter.output.JsonStream;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import net.jami.jams.ca.JamsCA;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+@WebServlet("/api/install/lastStep")
+public class InstallLastStepServlet extends HttpServlet {
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+        resp.setHeader("Access-Control-Allow-Origin", JamsCA.serverDomain);
+        HashMap<String,String> payload = new HashMap<>();
+        payload.put("uri",CachedObjects.endpoint);
+        resp.getOutputStream().write(JsonStream.serialize(resp).getBytes());
+    }
+}
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/StartInstallServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/StartInstallServlet.java
index 0e34525f828e2ec87519623c55ee1823730a6ab7..a3de6eee0d1ae8dcbb287652af5f31cd23c2892a 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/StartInstallServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/install/StartInstallServlet.java
@@ -24,19 +24,21 @@ package net.jami.jams.server.servlets.api.install;
 
 import com.jsoniter.JsonIterator;
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.authentication.AuthenticationSourceType;
 import net.jami.jams.common.authmodule.AuthTokenResponse;
+import net.jami.jams.common.dao.StatementElement;
 import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.objects.requests.CredentialsRequest;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.common.objects.user.User;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.util.List;
 
 import static net.jami.jams.server.Server.dataStore;
 import static net.jami.jams.server.servlets.api.auth.login.AuthRequestProcessor.processUsernamePasswordAuth;
@@ -48,9 +50,15 @@ public class StartInstallServlet extends HttpServlet {
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         //Here we must decide which page to show - login or sign-up
         StatementList statementList = new StatementList();
-        statementList.setStatements(null);
-        if(dataStore.getUserDao().getObjects(statementList).size() != 0) resp.setHeader("showLogin","true");
-        else resp.setHeader("showLogin","false");
+        StatementElement statementElement = new StatementElement("username","=","*","");
+        statementList.addStatement(statementElement);
+
+        List<User> results = dataStore.getUserDao().getObjects(statementList);
+        if(results.size() > 0)
+            resp.setStatus(404);
+        else
+            resp.setStatus(200);
+
     }
 
     @Override
@@ -82,7 +90,7 @@ public class StartInstallServlet extends HttpServlet {
         user.setAccessLevel(AccessLevel.ADMIN);
         dataStore.getUserDao().storeObject(user);
         AuthTokenResponse res = processUsernamePasswordAuth(user.getUsername(),user.getPassword());
-        resp.getOutputStream().write(JsonStream.serialize(res).getBytes());
         CachedObjects.endpoint = "/api/install/ca";
+        resp.getOutputStream().write(JsonStream.serialize(res).getBytes());
     }
 }
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/jaminameserver/AddressServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/jaminameserver/AddressServlet.java
index 6ee648fa1b085158e08b577592fe89db9dc28b56..35ac6389780ccbcc4f0aa6e6447926a8bf0e3566 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/jaminameserver/AddressServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/jaminameserver/AddressServlet.java
@@ -23,13 +23,13 @@
 package net.jami.jams.server.servlets.api.jaminameserver;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.jami.AddrLookupResponse;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.nameServer;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/jaminameserver/NameServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/jaminameserver/NameServlet.java
index 5d2bce18ef9558ac668910799f0776045fac0e9e..c46edef94787fd384b63447d1e8800d203acb8e6 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/jaminameserver/NameServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/jaminameserver/NameServlet.java
@@ -23,13 +23,13 @@
 package net.jami.jams.server.servlets.api.jaminameserver;
 
 import com.jsoniter.output.JsonStream;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import net.jami.jams.common.jami.NameLookupResponse;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.nameServer;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/AdminApiFilter.java b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/AdminApiFilter.java
index 0cf7d3fcf3322820d97b2183eb57e537ad939fdd..4b137c2da175f5c3ec00d0e958a90757d1bdc1a6 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/AdminApiFilter.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/AdminApiFilter.java
@@ -25,18 +25,18 @@ package net.jami.jams.server.servlets.filters;
 import com.nimbusds.jose.JWSVerifier;
 import com.nimbusds.jose.crypto.RSASSAVerifier;
 import com.nimbusds.jwt.SignedJWT;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.annotation.WebFilter;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.annotation.WebFilter;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.extern.slf4j.Slf4j;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.server.Server;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.userAuthenticationModule;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/ApiFilter.java b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/ApiFilter.java
index a125c4e4e5aab338a623bb974f8a3607350f5f06..191481644a9069d641052caa8e1ed231fd87d368 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/ApiFilter.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/ApiFilter.java
@@ -25,17 +25,17 @@ package net.jami.jams.server.servlets.filters;
 import com.nimbusds.jose.JWSVerifier;
 import com.nimbusds.jose.crypto.RSASSAVerifier;
 import com.nimbusds.jwt.SignedJWT;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.annotation.WebFilter;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.annotation.WebFilter;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.extern.slf4j.Slf4j;
 import net.jami.jams.server.Server;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.userAuthenticationModule;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/InstallFilter.java b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/InstallFilter.java
index af6c2d9a52b189c490a5cd7f215dbc49252fea3c..97b0ff4cc22c9405549a8f4b8213049260bcc1b1 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/InstallFilter.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/InstallFilter.java
@@ -25,17 +25,17 @@ package net.jami.jams.server.servlets.filters;
 import com.nimbusds.jose.JWSVerifier;
 import com.nimbusds.jose.crypto.RSASSAVerifier;
 import com.nimbusds.jwt.SignedJWT;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.annotation.WebFilter;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.annotation.WebFilter;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.extern.slf4j.Slf4j;
 import net.jami.jams.server.Server;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.Date;
 
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/general/ServerStatusServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/general/ServerStatusServlet.java
index 70ba99577d04b5bbe991d6043c8d649468fc487a..1b3ba6078f67289468ccfaffeef8cc25a1501157 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/general/ServerStatusServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/general/ServerStatusServlet.java
@@ -22,18 +22,25 @@
 */
 package net.jami.jams.server.servlets.general;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import com.jsoniter.output.JsonStream;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import net.jami.jams.ca.JamsCA;
+import net.jami.jams.server.Server;
+
 import java.io.IOException;
+import java.util.HashMap;
 
 @WebServlet("/api/info")
 public class ServerStatusServlet extends HttpServlet {
 
     @Override
-    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        resp.getOutputStream().print("OK");
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+        resp.setHeader("Access-Control-Allow-Origin", JamsCA.serverDomain);
+        HashMap<String,String> statusInfo = new HashMap<>();
+        statusInfo.put("installed",String.valueOf(Server.isInstalled.get()));
+        resp.getOutputStream().write(JsonStream.serialize(statusInfo).getBytes());
     }
 }
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/x509/CRLServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/x509/CRLServlet.java
index f97915d2cf5379d9571d6e8007155770e5dbc49e..77c8d2f0a29404bc7dca0ce93904c9d54e990e1b 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/x509/CRLServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/x509/CRLServlet.java
@@ -22,11 +22,12 @@
 */
 package net.jami.jams.server.servlets.x509;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.certificateAuthority;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/x509/OCSPServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/x509/OCSPServlet.java
index 1034ce668e69c5b5f1ef7f97f9a08f6b0f8f3427..eeb0b3f18ae76f88cf952c71ff0142a7040e5ddb 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/x509/OCSPServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/x509/OCSPServlet.java
@@ -22,11 +22,12 @@
 */
 package net.jami.jams.server.servlets.x509;
 
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
 import java.io.IOException;
 
 import static net.jami.jams.server.Server.certificateAuthority;
diff --git a/jams-server/src/main/resources/webapp/css/countrySelect.css b/jams-server/src/main/resources/webapp/css/countrySelect.css
new file mode 100644
index 0000000000000000000000000000000000000000..36d77af226c0c1bb79c76ab1d50f2a0136fa6aaa
--- /dev/null
+++ b/jams-server/src/main/resources/webapp/css/countrySelect.css
@@ -0,0 +1,1205 @@
+.country-select{
+	position:relative;
+	display:inline-block
+}
+.country-select *{
+	-webkit-box-sizing:border-box;
+	box-sizing:border-box
+}
+.country-select .hide{
+	display:none
+}
+.country-select .v-hide{
+	visibility:hidden
+}
+.country-select input,
+.country-select input[type=text]{
+	position:relative;
+	z-index:0;
+	margin-top:0 !important;
+	margin-bottom:0 !important;
+	padding-right:36px;
+	margin-right:0
+}
+.country-select .flag-dropdown{
+	position:absolute;
+	top:0;
+	bottom:0;
+	right:0;
+	padding:1px
+}
+.country-select .selected-flag{
+	z-index:1;
+	position:relative;
+	width:36px;
+	height:100%;
+	padding:0 0 0 8px
+}
+.country-select .selected-flag .flag{
+	position:absolute;
+	top:0;
+	bottom:0;
+	margin:auto
+}
+.country-select .selected-flag .arrow{
+	position:absolute;
+	top:50%;
+	margin-top:-2px;
+	right:6px;
+	width:0;
+	height:0;
+	border-left:3px solid transparent;
+	border-right:3px solid transparent;
+	border-top:4px solid #555
+}
+.country-select .selected-flag .arrow.up{
+	border-top:none;
+	border-bottom:4px solid #555
+}
+.country-select .country-list{
+	position:absolute;
+	z-index:2;
+	list-style:none;
+	text-align:left;
+	padding:0;
+	margin:0 0 0 -1px;
+	-webkit-box-shadow:1px 1px 4px rgba(0, 0, 0, 0.2);
+	box-shadow:1px 1px 4px rgba(0, 0, 0, 0.2);
+	background-color:white;
+	border:1px solid #ccc;
+	white-space:nowrap;
+	max-height:200px;
+	overflow-y:scroll
+}
+.country-select .country-list .flag{
+	display:inline-block;
+	width:20px
+}
+@media (max-width: 500px){
+	.country-select .country-list{
+		white-space:normal
+	}
+}
+.country-select .country-list .divider{
+	padding-bottom:5px;
+	margin-bottom:5px;
+	border-bottom:1px solid #ccc
+}
+.country-select .country-list .country{
+	padding:5px 10px
+}
+.country-select .country-list .country.highlight{
+	background-color:rgba(0, 0, 0, 0.05)
+}
+.country-select .country-list .flag,
+.country-select .country-list .country-name{
+	vertical-align:middle
+}
+.country-select .country-list .flag{
+	margin-right:6px
+}
+.country-select.inside input,
+.country-select.inside input[type=text]{
+	padding-right:6px;
+	padding-left:52px;
+	margin-left:0
+}
+.country-select.inside .flag-dropdown{
+	right:auto;
+	left:0
+}
+.country-select.inside .selected-flag{
+	width:46px
+}
+.country-select.inside .flag-dropdown:hover{
+	cursor:pointer
+}
+.country-select.inside .flag-dropdown:hover .selected-flag{
+	background-color:rgba(0, 0, 0, 0.05)
+}
+.country-select.inside input[disabled] + .flag-dropdown:hover,
+.country-select.inside input[readonly] + .flag-dropdown:hover{
+	cursor:default
+}
+.country-select.inside input[disabled] + .flag-dropdown:hover .selected-flag,
+.country-select.inside input[readonly] + .flag-dropdown:hover .selected-flag{
+	background-color:transparent
+}
+.country-select .flag{
+	width:20px;
+	height:15px;
+	-webkit-box-shadow:0px 0px 1px 0px #888;
+	box-shadow:0px 0px 1px 0px #888;
+	background-image:url("../images/flags.png");
+	background-repeat:no-repeat;
+	background-color:#dbdbdb;
+	background-position:20px 0
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2),
+only screen and (min--moz-device-pixel-ratio: 2),
+only screen and (min-device-pixel-ratio: 2),
+only screen and (min-resolution: 192dpi),
+only screen and (min-resolution: 2dppx){
+	.country-select .flag{
+		background-image:url("../images/flags@2x.png")
+	}
+}
+.country-select .flag{
+	width:20px
+}
+.country-select .flag.be{
+	width:18px
+}
+.country-select .flag.ch{
+	width:15px
+}
+.country-select .flag.mc{
+	width:19px
+}
+.country-select .flag.ne{
+	width:18px
+}
+.country-select .flag.np{
+	width:13px
+}
+.country-select .flag.va{
+	width:15px
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2),
+only screen and (min--moz-device-pixel-ratio: 2),
+only screen and (min-device-pixel-ratio: 2),
+only screen and (min-resolution: 192dpi),
+only screen and (min-resolution: 2dppx){
+	.country-select .flag{
+		background-size:5630px 15px
+	}
+}
+.country-select .flag.ac{
+	height:10px;
+	background-position:0px 0px
+}
+.country-select .flag.ad{
+	height:14px;
+	background-position:-22px 0px
+}
+.country-select .flag.ae{
+	height:10px;
+	background-position:-44px 0px
+}
+.country-select .flag.af{
+	height:14px;
+	background-position:-66px 0px
+}
+.country-select .flag.ag{
+	height:14px;
+	background-position:-88px 0px
+}
+.country-select .flag.ai{
+	height:10px;
+	background-position:-110px 0px
+}
+.country-select .flag.al{
+	height:15px;
+	background-position:-132px 0px
+}
+.country-select .flag.am{
+	height:10px;
+	background-position:-154px 0px
+}
+.country-select .flag.ao{
+	height:14px;
+	background-position:-176px 0px
+}
+.country-select .flag.aq{
+	height:14px;
+	background-position:-198px 0px
+}
+.country-select .flag.ar{
+	height:13px;
+	background-position:-220px 0px
+}
+.country-select .flag.as{
+	height:10px;
+	background-position:-242px 0px
+}
+.country-select .flag.at{
+	height:14px;
+	background-position:-264px 0px
+}
+.country-select .flag.au{
+	height:10px;
+	background-position:-286px 0px
+}
+.country-select .flag.aw{
+	height:14px;
+	background-position:-308px 0px
+}
+.country-select .flag.ax{
+	height:13px;
+	background-position:-330px 0px
+}
+.country-select .flag.az{
+	height:10px;
+	background-position:-352px 0px
+}
+.country-select .flag.ba{
+	height:10px;
+	background-position:-374px 0px
+}
+.country-select .flag.bb{
+	height:14px;
+	background-position:-396px 0px
+}
+.country-select .flag.bd{
+	height:12px;
+	background-position:-418px 0px
+}
+.country-select .flag.be{
+	height:15px;
+	background-position:-440px 0px
+}
+.country-select .flag.bf{
+	height:14px;
+	background-position:-460px 0px
+}
+.country-select .flag.bg{
+	height:12px;
+	background-position:-482px 0px
+}
+.country-select .flag.bh{
+	height:12px;
+	background-position:-504px 0px
+}
+.country-select .flag.bi{
+	height:12px;
+	background-position:-526px 0px
+}
+.country-select .flag.bj{
+	height:14px;
+	background-position:-548px 0px
+}
+.country-select .flag.bl{
+	height:14px;
+	background-position:-570px 0px
+}
+.country-select .flag.bm{
+	height:10px;
+	background-position:-592px 0px
+}
+.country-select .flag.bn{
+	height:10px;
+	background-position:-614px 0px
+}
+.country-select .flag.bo{
+	height:14px;
+	background-position:-636px 0px
+}
+.country-select .flag.bq{
+	height:14px;
+	background-position:-658px 0px
+}
+.country-select .flag.br{
+	height:14px;
+	background-position:-680px 0px
+}
+.country-select .flag.bs{
+	height:10px;
+	background-position:-702px 0px
+}
+.country-select .flag.bt{
+	height:14px;
+	background-position:-724px 0px
+}
+.country-select .flag.bv{
+	height:15px;
+	background-position:-746px 0px
+}
+.country-select .flag.bw{
+	height:14px;
+	background-position:-768px 0px
+}
+.country-select .flag.by{
+	height:10px;
+	background-position:-790px 0px
+}
+.country-select .flag.bz{
+	height:14px;
+	background-position:-812px 0px
+}
+.country-select .flag.ca{
+	height:10px;
+	background-position:-834px 0px
+}
+.country-select .flag.cc{
+	height:10px;
+	background-position:-856px 0px
+}
+.country-select .flag.cd{
+	height:15px;
+	background-position:-878px 0px
+}
+.country-select .flag.cf{
+	height:14px;
+	background-position:-900px 0px
+}
+.country-select .flag.cg{
+	height:14px;
+	background-position:-922px 0px
+}
+.country-select .flag.ch{
+	height:15px;
+	background-position:-944px 0px
+}
+.country-select .flag.ci{
+	height:14px;
+	background-position:-961px 0px
+}
+.country-select .flag.ck{
+	height:10px;
+	background-position:-983px 0px
+}
+.country-select .flag.cl{
+	height:14px;
+	background-position:-1005px 0px
+}
+.country-select .flag.cm{
+	height:14px;
+	background-position:-1027px 0px
+}
+.country-select .flag.cn{
+	height:14px;
+	background-position:-1049px 0px
+}
+.country-select .flag.co{
+	height:14px;
+	background-position:-1071px 0px
+}
+.country-select .flag.cp{
+	height:14px;
+	background-position:-1093px 0px
+}
+.country-select .flag.cr{
+	height:12px;
+	background-position:-1115px 0px
+}
+.country-select .flag.cu{
+	height:10px;
+	background-position:-1137px 0px
+}
+.country-select .flag.cv{
+	height:12px;
+	background-position:-1159px 0px
+}
+.country-select .flag.cw{
+	height:14px;
+	background-position:-1181px 0px
+}
+.country-select .flag.cx{
+	height:10px;
+	background-position:-1203px 0px
+}
+.country-select .flag.cy{
+	height:13px;
+	background-position:-1225px 0px
+}
+.country-select .flag.cz{
+	height:14px;
+	background-position:-1247px 0px
+}
+.country-select .flag.de{
+	height:12px;
+	background-position:-1269px 0px
+}
+.country-select .flag.dg{
+	height:10px;
+	background-position:-1291px 0px
+}
+.country-select .flag.dj{
+	height:14px;
+	background-position:-1313px 0px
+}
+.country-select .flag.dk{
+	height:15px;
+	background-position:-1335px 0px
+}
+.country-select .flag.dm{
+	height:10px;
+	background-position:-1357px 0px
+}
+.country-select .flag.do{
+	height:13px;
+	background-position:-1379px 0px
+}
+.country-select .flag.dz{
+	height:14px;
+	background-position:-1401px 0px
+}
+.country-select .flag.ea{
+	height:14px;
+	background-position:-1423px 0px
+}
+.country-select .flag.ec{
+	height:14px;
+	background-position:-1445px 0px
+}
+.country-select .flag.ee{
+	height:13px;
+	background-position:-1467px 0px
+}
+.country-select .flag.eg{
+	height:14px;
+	background-position:-1489px 0px
+}
+.country-select .flag.eh{
+	height:10px;
+	background-position:-1511px 0px
+}
+.country-select .flag.er{
+	height:10px;
+	background-position:-1533px 0px
+}
+.country-select .flag.es{
+	height:14px;
+	background-position:-1555px 0px
+}
+.country-select .flag.et{
+	height:10px;
+	background-position:-1577px 0px
+}
+.country-select .flag.eu{
+	height:14px;
+	background-position:-1599px 0px
+}
+.country-select .flag.fi{
+	height:12px;
+	background-position:-1621px 0px
+}
+.country-select .flag.fj{
+	height:10px;
+	background-position:-1643px 0px
+}
+.country-select .flag.fk{
+	height:10px;
+	background-position:-1665px 0px
+}
+.country-select .flag.fm{
+	height:11px;
+	background-position:-1687px 0px
+}
+.country-select .flag.fo{
+	height:15px;
+	background-position:-1709px 0px
+}
+.country-select .flag.fr{
+	height:14px;
+	background-position:-1731px 0px
+}
+.country-select .flag.ga{
+	height:15px;
+	background-position:-1753px 0px
+}
+.country-select .flag.gb{
+	height:10px;
+	background-position:-1775px 0px
+}
+.country-select .flag.gd{
+	height:12px;
+	background-position:-1797px 0px
+}
+.country-select .flag.ge{
+	height:14px;
+	background-position:-1819px 0px
+}
+.country-select .flag.gf{
+	height:14px;
+	background-position:-1841px 0px
+}
+.country-select .flag.gg{
+	height:14px;
+	background-position:-1863px 0px
+}
+.country-select .flag.gh{
+	height:14px;
+	background-position:-1885px 0px
+}
+.country-select .flag.gi{
+	height:10px;
+	background-position:-1907px 0px
+}
+.country-select .flag.gl{
+	height:14px;
+	background-position:-1929px 0px
+}
+.country-select .flag.gm{
+	height:14px;
+	background-position:-1951px 0px
+}
+.country-select .flag.gn{
+	height:14px;
+	background-position:-1973px 0px
+}
+.country-select .flag.gp{
+	height:14px;
+	background-position:-1995px 0px
+}
+.country-select .flag.gq{
+	height:14px;
+	background-position:-2017px 0px
+}
+.country-select .flag.gr{
+	height:14px;
+	background-position:-2039px 0px
+}
+.country-select .flag.gs{
+	height:10px;
+	background-position:-2061px 0px
+}
+.country-select .flag.gt{
+	height:13px;
+	background-position:-2083px 0px
+}
+.country-select .flag.gu{
+	height:11px;
+	background-position:-2105px 0px
+}
+.country-select .flag.gw{
+	height:10px;
+	background-position:-2127px 0px
+}
+.country-select .flag.gy{
+	height:12px;
+	background-position:-2149px 0px
+}
+.country-select .flag.hk{
+	height:14px;
+	background-position:-2171px 0px
+}
+.country-select .flag.hm{
+	height:10px;
+	background-position:-2193px 0px
+}
+.country-select .flag.hn{
+	height:10px;
+	background-position:-2215px 0px
+}
+.country-select .flag.hr{
+	height:10px;
+	background-position:-2237px 0px
+}
+.country-select .flag.ht{
+	height:12px;
+	background-position:-2259px 0px
+}
+.country-select .flag.hu{
+	height:10px;
+	background-position:-2281px 0px
+}
+.country-select .flag.ic{
+	height:14px;
+	background-position:-2303px 0px
+}
+.country-select .flag.id{
+	height:14px;
+	background-position:-2325px 0px
+}
+.country-select .flag.ie{
+	height:10px;
+	background-position:-2347px 0px
+}
+.country-select .flag.il{
+	height:15px;
+	background-position:-2369px 0px
+}
+.country-select .flag.im{
+	height:10px;
+	background-position:-2391px 0px
+}
+.country-select .flag.in{
+	height:14px;
+	background-position:-2413px 0px
+}
+.country-select .flag.io{
+	height:10px;
+	background-position:-2435px 0px
+}
+.country-select .flag.iq{
+	height:14px;
+	background-position:-2457px 0px
+}
+.country-select .flag.ir{
+	height:12px;
+	background-position:-2479px 0px
+}
+.country-select .flag.is{
+	height:15px;
+	background-position:-2501px 0px
+}
+.country-select .flag.it{
+	height:14px;
+	background-position:-2523px 0px
+}
+.country-select .flag.je{
+	height:12px;
+	background-position:-2545px 0px
+}
+.country-select .flag.jm{
+	height:10px;
+	background-position:-2567px 0px
+}
+.country-select .flag.jo{
+	height:10px;
+	background-position:-2589px 0px
+}
+.country-select .flag.jp{
+	height:14px;
+	background-position:-2611px 0px
+}
+.country-select .flag.ke{
+	height:14px;
+	background-position:-2633px 0px
+}
+.country-select .flag.kg{
+	height:12px;
+	background-position:-2655px 0px
+}
+.country-select .flag.kh{
+	height:13px;
+	background-position:-2677px 0px
+}
+.country-select .flag.ki{
+	height:10px;
+	background-position:-2699px 0px
+}
+.country-select .flag.km{
+	height:12px;
+	background-position:-2721px 0px
+}
+.country-select .flag.kn{
+	height:14px;
+	background-position:-2743px 0px
+}
+.country-select .flag.kp{
+	height:10px;
+	background-position:-2765px 0px
+}
+.country-select .flag.kr{
+	height:14px;
+	background-position:-2787px 0px
+}
+.country-select .flag.kw{
+	height:10px;
+	background-position:-2809px 0px
+}
+.country-select .flag.ky{
+	height:10px;
+	background-position:-2831px 0px
+}
+.country-select .flag.kz{
+	height:10px;
+	background-position:-2853px 0px
+}
+.country-select .flag.la{
+	height:14px;
+	background-position:-2875px 0px
+}
+.country-select .flag.lb{
+	height:14px;
+	background-position:-2897px 0px
+}
+.country-select .flag.lc{
+	height:10px;
+	background-position:-2919px 0px
+}
+.country-select .flag.li{
+	height:12px;
+	background-position:-2941px 0px
+}
+.country-select .flag.lk{
+	height:10px;
+	background-position:-2963px 0px
+}
+.country-select .flag.lr{
+	height:11px;
+	background-position:-2985px 0px
+}
+.country-select .flag.ls{
+	height:14px;
+	background-position:-3007px 0px
+}
+.country-select .flag.lt{
+	height:12px;
+	background-position:-3029px 0px
+}
+.country-select .flag.lu{
+	height:12px;
+	background-position:-3051px 0px
+}
+.country-select .flag.lv{
+	height:10px;
+	background-position:-3073px 0px
+}
+.country-select .flag.ly{
+	height:10px;
+	background-position:-3095px 0px
+}
+.country-select .flag.ma{
+	height:14px;
+	background-position:-3117px 0px
+}
+.country-select .flag.mc{
+	height:15px;
+	background-position:-3139px 0px
+}
+.country-select .flag.md{
+	height:10px;
+	background-position:-3160px 0px
+}
+.country-select .flag.me{
+	height:10px;
+	background-position:-3182px 0px
+}
+.country-select .flag.mf{
+	height:14px;
+	background-position:-3204px 0px
+}
+.country-select .flag.mg{
+	height:14px;
+	background-position:-3226px 0px
+}
+.country-select .flag.mh{
+	height:11px;
+	background-position:-3248px 0px
+}
+.country-select .flag.mk{
+	height:10px;
+	background-position:-3270px 0px
+}
+.country-select .flag.ml{
+	height:14px;
+	background-position:-3292px 0px
+}
+.country-select .flag.mm{
+	height:14px;
+	background-position:-3314px 0px
+}
+.country-select .flag.mn{
+	height:10px;
+	background-position:-3336px 0px
+}
+.country-select .flag.mo{
+	height:14px;
+	background-position:-3358px 0px
+}
+.country-select .flag.mp{
+	height:10px;
+	background-position:-3380px 0px
+}
+.country-select .flag.mq{
+	height:14px;
+	background-position:-3402px 0px
+}
+.country-select .flag.mr{
+	height:14px;
+	background-position:-3424px 0px
+}
+.country-select .flag.ms{
+	height:10px;
+	background-position:-3446px 0px
+}
+.country-select .flag.mt{
+	height:14px;
+	background-position:-3468px 0px
+}
+.country-select .flag.mu{
+	height:14px;
+	background-position:-3490px 0px
+}
+.country-select .flag.mv{
+	height:14px;
+	background-position:-3512px 0px
+}
+.country-select .flag.mw{
+	height:14px;
+	background-position:-3534px 0px
+}
+.country-select .flag.mx{
+	height:12px;
+	background-position:-3556px 0px
+}
+.country-select .flag.my{
+	height:10px;
+	background-position:-3578px 0px
+}
+.country-select .flag.mz{
+	height:14px;
+	background-position:-3600px 0px
+}
+.country-select .flag.na{
+	height:14px;
+	background-position:-3622px 0px
+}
+.country-select .flag.nc{
+	height:10px;
+	background-position:-3644px 0px
+}
+.country-select .flag.ne{
+	height:15px;
+	background-position:-3666px 0px
+}
+.country-select .flag.nf{
+	height:10px;
+	background-position:-3686px 0px
+}
+.country-select .flag.ng{
+	height:10px;
+	background-position:-3708px 0px
+}
+.country-select .flag.ni{
+	height:12px;
+	background-position:-3730px 0px
+}
+.country-select .flag.nl{
+	height:14px;
+	background-position:-3752px 0px
+}
+.country-select .flag.no{
+	height:15px;
+	background-position:-3774px 0px
+}
+.country-select .flag.np{
+	height:15px;
+	background-position:-3796px 0px;
+	background-color:transparent
+}
+.country-select .flag.nr{
+	height:10px;
+	background-position:-3811px 0px
+}
+.country-select .flag.nu{
+	height:10px;
+	background-position:-3833px 0px
+}
+.country-select .flag.nz{
+	height:10px;
+	background-position:-3855px 0px
+}
+.country-select .flag.om{
+	height:10px;
+	background-position:-3877px 0px
+}
+.country-select .flag.pa{
+	height:14px;
+	background-position:-3899px 0px
+}
+.country-select .flag.pe{
+	height:14px;
+	background-position:-3921px 0px
+}
+.country-select .flag.pf{
+	height:14px;
+	background-position:-3943px 0px
+}
+.country-select .flag.pg{
+	height:15px;
+	background-position:-3965px 0px
+}
+.country-select .flag.ph{
+	height:10px;
+	background-position:-3987px 0px
+}
+.country-select .flag.pk{
+	height:14px;
+	background-position:-4009px 0px
+}
+.country-select .flag.pl{
+	height:13px;
+	background-position:-4031px 0px
+}
+.country-select .flag.pm{
+	height:14px;
+	background-position:-4053px 0px
+}
+.country-select .flag.pn{
+	height:10px;
+	background-position:-4075px 0px
+}
+.country-select .flag.pr{
+	height:14px;
+	background-position:-4097px 0px
+}
+.country-select .flag.ps{
+	height:10px;
+	background-position:-4119px 0px
+}
+.country-select .flag.pt{
+	height:14px;
+	background-position:-4141px 0px
+}
+.country-select .flag.pw{
+	height:13px;
+	background-position:-4163px 0px
+}
+.country-select .flag.py{
+	height:11px;
+	background-position:-4185px 0px
+}
+.country-select .flag.qa{
+	height:8px;
+	background-position:-4207px 0px
+}
+.country-select .flag.re{
+	height:14px;
+	background-position:-4229px 0px
+}
+.country-select .flag.ro{
+	height:14px;
+	background-position:-4251px 0px
+}
+.country-select .flag.rs{
+	height:14px;
+	background-position:-4273px 0px
+}
+.country-select .flag.ru{
+	height:14px;
+	background-position:-4295px 0px
+}
+.country-select .flag.rw{
+	height:14px;
+	background-position:-4317px 0px
+}
+.country-select .flag.sa{
+	height:14px;
+	background-position:-4339px 0px
+}
+.country-select .flag.sb{
+	height:10px;
+	background-position:-4361px 0px
+}
+.country-select .flag.sc{
+	height:10px;
+	background-position:-4383px 0px
+}
+.country-select .flag.sd{
+	height:10px;
+	background-position:-4405px 0px
+}
+.country-select .flag.se{
+	height:13px;
+	background-position:-4427px 0px
+}
+.country-select .flag.sg{
+	height:14px;
+	background-position:-4449px 0px
+}
+.country-select .flag.sh{
+	height:10px;
+	background-position:-4471px 0px
+}
+.country-select .flag.si{
+	height:10px;
+	background-position:-4493px 0px
+}
+.country-select .flag.sj{
+	height:15px;
+	background-position:-4515px 0px
+}
+.country-select .flag.sk{
+	height:14px;
+	background-position:-4537px 0px
+}
+.country-select .flag.sl{
+	height:14px;
+	background-position:-4559px 0px
+}
+.country-select .flag.sm{
+	height:15px;
+	background-position:-4581px 0px
+}
+.country-select .flag.sn{
+	height:14px;
+	background-position:-4603px 0px
+}
+.country-select .flag.so{
+	height:14px;
+	background-position:-4625px 0px
+}
+.country-select .flag.sr{
+	height:14px;
+	background-position:-4647px 0px
+}
+.country-select .flag.ss{
+	height:10px;
+	background-position:-4669px 0px
+}
+.country-select .flag.st{
+	height:10px;
+	background-position:-4691px 0px
+}
+.country-select .flag.sv{
+	height:12px;
+	background-position:-4713px 0px
+}
+.country-select .flag.sx{
+	height:14px;
+	background-position:-4735px 0px
+}
+.country-select .flag.sy{
+	height:14px;
+	background-position:-4757px 0px
+}
+.country-select .flag.sz{
+	height:14px;
+	background-position:-4779px 0px
+}
+.country-select .flag.ta{
+	height:10px;
+	background-position:-4801px 0px
+}
+.country-select .flag.tc{
+	height:10px;
+	background-position:-4823px 0px
+}
+.country-select .flag.td{
+	height:14px;
+	background-position:-4845px 0px
+}
+.country-select .flag.tf{
+	height:14px;
+	background-position:-4867px 0px
+}
+.country-select .flag.tg{
+	height:13px;
+	background-position:-4889px 0px
+}
+.country-select .flag.th{
+	height:14px;
+	background-position:-4911px 0px
+}
+.country-select .flag.tj{
+	height:10px;
+	background-position:-4933px 0px
+}
+.country-select .flag.tk{
+	height:10px;
+	background-position:-4955px 0px
+}
+.country-select .flag.tl{
+	height:10px;
+	background-position:-4977px 0px
+}
+.country-select .flag.tm{
+	height:14px;
+	background-position:-4999px 0px
+}
+.country-select .flag.tn{
+	height:14px;
+	background-position:-5021px 0px
+}
+.country-select .flag.to{
+	height:10px;
+	background-position:-5043px 0px
+}
+.country-select .flag.tr{
+	height:14px;
+	background-position:-5065px 0px
+}
+.country-select .flag.tt{
+	height:12px;
+	background-position:-5087px 0px
+}
+.country-select .flag.tv{
+	height:10px;
+	background-position:-5109px 0px
+}
+.country-select .flag.tw{
+	height:14px;
+	background-position:-5131px 0px
+}
+.country-select .flag.tz{
+	height:14px;
+	background-position:-5153px 0px
+}
+.country-select .flag.ua{
+	height:14px;
+	background-position:-5175px 0px
+}
+.country-select .flag.ug{
+	height:14px;
+	background-position:-5197px 0px
+}
+.country-select .flag.um{
+	height:11px;
+	background-position:-5219px 0px
+}
+.country-select .flag.us{
+	height:11px;
+	background-position:-5241px 0px
+}
+.country-select .flag.uy{
+	height:14px;
+	background-position:-5263px 0px
+}
+.country-select .flag.uz{
+	height:10px;
+	background-position:-5285px 0px
+}
+.country-select .flag.va{
+	height:15px;
+	background-position:-5307px 0px
+}
+.country-select .flag.vc{
+	height:14px;
+	background-position:-5324px 0px
+}
+.country-select .flag.ve{
+	height:14px;
+	background-position:-5346px 0px
+}
+.country-select .flag.vg{
+	height:10px;
+	background-position:-5368px 0px
+}
+.country-select .flag.vi{
+	height:14px;
+	background-position:-5390px 0px
+}
+.country-select .flag.vn{
+	height:14px;
+	background-position:-5412px 0px
+}
+.country-select .flag.vu{
+	height:12px;
+	background-position:-5434px 0px
+}
+.country-select .flag.wf{
+	height:14px;
+	background-position:-5456px 0px
+}
+.country-select .flag.ws{
+	height:10px;
+	background-position:-5478px 0px
+}
+.country-select .flag.xk{
+	height:15px;
+	background-position:-5500px 0px
+}
+.country-select .flag.ye{
+	height:14px;
+	background-position:-5522px 0px
+}
+.country-select .flag.yt{
+	height:14px;
+	background-position:-5544px 0px
+}
+.country-select .flag.za{
+	height:14px;
+	background-position:-5566px 0px
+}
+.country-select .flag.zm{
+	height:14px;
+	background-position:-5588px 0px
+}
+.country-select .flag.zw{
+	height:10px;
+	background-position:-5610px 0px
+}
\ No newline at end of file
diff --git a/jams-server/src/main/resources/webapp/js/api.js b/jams-server/src/main/resources/webapp/js/api.js
index a033bd8306d05f979b3a15b668b2ed1c7dd6026c..878387dcdee5d2dc50d35f25e7a0513871717621 100644
--- a/jams-server/src/main/resources/webapp/js/api.js
+++ b/jams-server/src/main/resources/webapp/js/api.js
@@ -36,19 +36,19 @@ var url_port = backend_address.port;
 var ca_setup_page = 'ca-setup.html';
 var identity_management_page = 'identity-management.html';
 var server_parameters_page = 'server-parameters.html';
-var api_path_post_install_admin = '/api/jumpstart/setupAdmin';
+var api_path_post_install_admin = '/api/install/start';
 var api_path_post_auth_login = '/api/auth/login';
-var api_path_post_install_ca = '/api/jumpstart/setupCA';
-var api_path_post_install_auth = '/api/jumpstart/setupAuth';
+var api_path_post_install_ca = '/api/install/ca';
+var api_path_post_install_auth = '/api/install/auth';
 var api_path_post_install_server = '/api/jumpstart/setupServer';
-var api_path_get_install_lastKnownStep = '/api/jumpstart/lastStep';
+var api_path_get_install_lastKnownStep = '/api/install/lastStep';
 var api_path_get_auth_users = '/api/auth/users';
 var api_path_get_auth_user_search = '/api/auth/users';
 var api_path_get_auth_devices = '/api/auth/devices';
 var api_path_delete_auth_user_revoke = '/api/auth/user';
 var api_path_delete_auth_device_revoke = '/api/auth/device';
 var api_path_rename_device = '/api/auth/device';
-var api_path_get_server_status = '/api/status';
+var api_path_get_server_status = '/api/info';
 var api_path_post_api_check = '/api/auth/check';
 var api_path_get_logout = '/api/auth/logout';
 var api_path_get_post_configuration_auth_service = '/api/configuration/authservice';
@@ -81,10 +81,23 @@ function ajaxApiCall(api_path, request_type, data, credentials, callBackFunction
         }};
 
     // pass credentials in the header
-    if (credentials){
+    if (credentials) {
         ajax['headers'] =  {
             "Authorization": "Basic " + btoa(credentials["username"] + ':' + credentials["password"]),
-        }}
+        }
+    }
+
+    if (window.localStorage.getItem('access_token')) {
+
+        var jwt = localStorage.getItem('access_token');
+        console.log(jwt);
+        console.log(data);
+
+        ajax['headers'] =  {
+            "Bearer": jwt,
+        }
+    }
+
     // pass data in the header
     if (data) {
         if (api_path == api_path_get_user_extended_data || api_path == api_path_get_auth_user_search || api_path == api_path_get_user_needs_reset)
@@ -95,8 +108,20 @@ function ajaxApiCall(api_path, request_type, data, credentials, callBackFunction
             ajax['data'] = data;
         }
         else {
+
+            if (window.localStorage.getItem('access_token')) {
+
+                var jwt = localStorage.getItem('access_token');
+                console.log(jwt);
+
+                ajax['headers'] =  {
+                    "Bearer": jwt,
+                }
+            }
+
             ajax['headers'] =  {
-                "Content-type":"application/json"
+                "Content-type":"application/json",
+                "Bearer": jwt
             }
             ajax['data'] = JSON.stringify(data);
         }
@@ -118,6 +143,11 @@ function set_installation_response(url, completed){
         if (data) {
             if (data.status == 404) {
                 $('#installCompleteModalCenter').modal('show');
+            } else if ((data.status == 500 || data.status == 0) && url.includes("usePublicNS"))   {
+                $('#installErrorModalLongTitle').text('Connection Failed');
+                $('#install-error-id').text('The information provided appears to be incorrect, the connection to the directory has failed.' +
+                                              'Please check the information and credentials provided and try again.');
+                $('#installErrorModalCenter').modal('show');
             }
             // server error
             else if (data.status == 500 || data.status == 0) {
@@ -125,6 +155,8 @@ function set_installation_response(url, completed){
             }
             // 200 OK
             else if (data.status = 200) {
+                $('#installErrorModalLongTitle').text('Server Error');
+                $('#install-error-id').text('Invalid data.');
                 window.location.replace(url);
             }
         }
diff --git a/jams-server/src/main/resources/webapp/js/auth.js b/jams-server/src/main/resources/webapp/js/auth.js
index 24a003efd31262c89a2a2e64673d78bfe8c42990..c298860c11588e4443f30cdd170590eca9041a07 100644
--- a/jams-server/src/main/resources/webapp/js/auth.js
+++ b/jams-server/src/main/resources/webapp/js/auth.js
@@ -68,17 +68,18 @@ function authorizedUser(username) {
 }
 
 function noAuthorization() {
-  window.location.replace("login.jsp");
+  window.location.replace("signup.html");
 }
 
 function getAdminStatus() {
     var adminStatus = getCookie(keyAdmin);
-    if (adminStatus) {
-      return true;
-    }
-    else {
-      return false;
-    }
+    // if (adminStatus) {
+    //   return true;
+    // }
+    // else {
+    //   return false;
+    // }
+    return true;
 }
 
 function getUser() {
@@ -86,7 +87,7 @@ function getUser() {
 }
 
 function getApiCheck() {
-  ajaxApiCall(api_path_post_api_check, 'GET', null, null, setApiStatus, false);
+    apiCheck = true;
 }
 
 function setApiStatus(data, statusCode, jqXHR) {
@@ -112,7 +113,7 @@ function serverConfigStatus(data, statusCode, jqXHR) {
       else if (!getAdminStatus() && getUser() && (!current_uri.includes('user.html'))) {
         authorizedUser(getUser());
       }
-      else if (!getAdminStatus() && !getUser() && (!current_uri.includes('login.jsp'))) {
+      else if (!getAdminStatus() && !getUser() && (!current_uri.includes('signup.html'))) {
         noAuthorization();
       }
     }
@@ -120,37 +121,37 @@ function serverConfigStatus(data, statusCode, jqXHR) {
     else if (getAdminStatus()) {
       ajaxApiCall(api_path_get_install_lastKnownStep, 'GET', null, null, lastServerConfigurationStepUri, false);
     }
-    else if (!current_uri.includes('login.jsp')) {
+    else if (!current_uri.includes('signup.html')) {
       noAuthorization();
     }
   }
-  else if (!current_uri.includes('login.jsp') && !current_uri.includes('new-password.html')) {
+  else if (!current_uri.includes('signup.html') && !current_uri.includes('new-password.html')) {
     noAuthorization();
   }
 }
 
 function lastServerConfigurationStepUri(data, statusCode, jqXHR) {
-  if (jqXHR.status == 200) {
-    // lastKnownStep
-    var current_page = false;
-    uri_endpoint = data.uri;
-    if (uri_endpoint == api_path_post_install_ca) {
-        uri = ca_setup_page;
-    }
-    else if (uri_endpoint == api_path_post_install_auth) {
-        uri = identity_management_page;
-    }
-    else if (uri_endpoint == api_path_post_install_server) {
-        uri = server_parameters_page;
-    }
-    // redirect to lastKnownStep
-    if (!(current_uri.includes(uri))) {
-      window.location.replace(uri);
-    }
-  }
-  else {
-    invalidLogin();
-  }
+  // if (jqXHR.status == 200) {
+  //   // lastKnownStep
+  //   var current_page = false;
+  //   uri_endpoint = data.uri;
+  //   if (uri_endpoint == api_path_post_install_ca) {
+  //       uri = ca_setup_page;
+  //   }
+  //   else if (uri_endpoint == api_path_post_install_auth) {
+  //       uri = identity_management_page;
+  //   }
+  //   else if (uri_endpoint == api_path_post_install_server) {
+  //       uri = server_parameters_page;
+  //   }
+  //   // redirect to lastKnownStep
+  //   if (!(current_uri.includes(uri))) {
+  //     window.location.replace(uri);
+  //   }
+  // }
+  // else {
+  //   invalidLogin();
+  // }
 }
 
 function invalidLogin() {
diff --git a/jams-server/src/main/resources/webapp/js/config.js b/jams-server/src/main/resources/webapp/js/config.js
index e2b487e1256b0c5de3220af74bd4b0de40a58728..56a22549a12d6c07d09e7c188ec87da9851ea4bd 100644
--- a/jams-server/src/main/resources/webapp/js/config.js
+++ b/jams-server/src/main/resources/webapp/js/config.js
@@ -36,8 +36,10 @@ function getAllConfigurations(data, statusCode, jqXHR) {
     var userValidity = data.userValidity;
     var ldapConfigurations = data.ldapConfigurations;
     var adConfigurations = data.activeDirectoryConfgurations;
+    // var hsqlConfigurations = data.hsqlConfigurations;
     setADblocks(adConfigurations);
     setLDAPblocks(ldapConfigurations);
+    // setHSQLblocks(hsqlConfigurations);
     setServerParameters(domain,crlValidity,deviceValidity,userValidity);
     $('[data-toggle="tooltip"]').tooltip();
     if(sessionStorage.getItem("auth_added") !== ""){
@@ -123,7 +125,6 @@ $('#addAuthenticationAD').on('click', function () {
 
 // submit create/edit AD authentication
 $(document).on("submit","#AD-form",function (e) {
-  console.log("submit AD form");
   e.preventDefault();
   setADparametersData($(this));
 });
@@ -155,7 +156,7 @@ function setADparametersData(form) {
   }
 }
 
-// set LDAP configruation blocks
+// set AD configruation blocks
 function setADblocks(ad_list) {
   $.each(ad_list, function (index, ad) {
     // set the display values
@@ -174,6 +175,69 @@ function setADblocks(ad_list) {
   });
 }
 
+/*======== HSQL =============*/
+
+// display add HSQL template form
+// $('#addAuthenticationHSQL').on('click', function () {
+//     $('#HSQL-form-submit').text('Create HSQL authentication service');
+//     $('#HSQLModalCenter').modal('show');
+//     $("#HSQL-form")[0].reset();
+// });
+//
+// // submit create/edit AD authentication
+// $(document).on("submit","#HSQL-form",function (e) {
+//     e.preventDefault();
+//     setHSQLparametersData($(this));
+// });
+//
+// function setHSQLparametersData(form) {
+//     event.preventDefault();
+//     var checked = "";
+//
+//     if ($('#publicNS')[0].checked)
+//         checked = "http://ns.jami.net";
+//     else
+//         checked = window.location.origin;
+//
+//     var data = {
+//         "CN": checked
+//     };
+//     // edit post request
+//     if (data) {
+//         ajaxApiCall(api_path_get_post_configuration_auth_service,'POST', data, null, callbackAuthentication);
+//     }
+//     // create post request
+//     else {
+//         delete data['configId'];
+//         auth_type = "HSQL";
+//         auth_action = "CREATE";
+//         ajaxApiCall(api_path_get_post_configuration_auth_service,'POST', data, null, callbackAuthentication);
+//     }
+// }
+//
+// // set HSQL configuration blocks
+// function setHSQLblocks(hsql_list) {
+//     $.each(hsql_list, function (index, hsql) {
+//         // set the display values
+//         var hsql_template = $($('#hsqlTemplate').html());
+//         var $new_hsql = hsql_template.clone();
+//         var usePublicNS = '';
+//
+//         if (hsql_list[0].cN == "http://ns.jami.net")
+//             usePublicNS = "Yes";
+//         else
+//             usePublicNS = "No";
+//
+//         $new_hsql.find('.mr-2').html("HSQL Authentication");
+//         $new_hsql.find('.mr-3').html("Using public nameserver: " + usePublicNS);
+//         var edit_button = $new_hsql.find('.edit-auth').attr('data-id', "HSQL");
+//         var delete_button = $new_hsql.find('.delete-auth').attr('data-id', "HSQL");
+//         $(edit_button).on( 'click', editAuthorizationHSQL);
+//         $(delete_button).on( 'click', deleteAuthorization);
+//         $new_hsql.insertAfter('#authDataWrapper');
+//     });
+// }
+
 /*======== SERVER PARAMETERS =============*/
 
 // submit edit serverParameters
@@ -402,10 +466,33 @@ function editAuthorizationAD () {
   $('#ADModalCenter').modal('show');
 }
 
+// function editAuthorizationHSQL () {
+//     var auth_id = $(this).attr('data-id');
+//     var data = $('[data-configId="' + auth_id + '"]');
+//     var value = '';
+//     var form = $('#' + $(data).attr('data-authentication-type') + "-form");
+//     $.each($(form).serializeArray(), function (i, field) {
+//         // pre fill fields
+//         if (selected_names.indexOf(field.name) >= 0) {
+//             $("option[value='" + value + "']", "#HSQL-form").prop('selected', true);
+//         }
+//         else {
+//             $("input[name='" + field.name + "']", "#HSQL-form").val(value);
+//         }
+//     });
+//     // set value for radio button
+//     $('#HSQL-form-submit').text('Update HSQL authentication service');
+//     $('#HSQLModalCenter').modal('show');
+// }
+
 // handles authentication delete modal behaviour
 function deleteAuthorization() {
   var config_id = $(this).attr('data-id');
   var auth_type = $(this).attr('data-type');
+
+    if (auth_type == "")
+        auth_type = "HSQL";
+
   $('#deleteAuthorizationBody').text('Are you sure you want to remove this ' + auth_type + ' connection? Users will not be able to connect to Jami using their ' + auth_type + ' credentials.');
   $('#delete-auth-service-confirm').attr('data-configId', config_id);
   $('#deleteAuthorizationModal').modal('show');
@@ -442,6 +529,13 @@ function callbackAuthentication (data, statusCode, jqXHR){
         $('.configMessageAuth').remove();
       });
     }
+    // if ($('#HSQLModalCenter').is(':visible')) {
+    //   $('.configMessageAuth').remove();
+    //   $('#HSQLModalLongTitle').before('<div class="configMessageAuth" id="configMessageError"><i class="fa fa-exclamation-circle" aria-hidden="true"></i>An error has occured, please try again...</div>');
+    //   $("#HSQLModalCenter").on("hidden.bs.modal", function () {
+    //       $('.configMessageAuth').remove();
+    //   });
+    // }
   }
 }
 
diff --git a/jams-server/src/main/resources/webapp/js/cookies-manager.js b/jams-server/src/main/resources/webapp/js/cookies-manager.js
index 35de281caf10c83796827894afae6e4374867869..e3e23f662cc4f60f64cef1373ba4ec0bf9a75e14 100644
--- a/jams-server/src/main/resources/webapp/js/cookies-manager.js
+++ b/jams-server/src/main/resources/webapp/js/cookies-manager.js
@@ -24,12 +24,9 @@ function setCookie(key, value, expiry) {
     document.cookie = key + '=' + value + ';expires=' + expires.toUTCString();
 }
 
-/* If you want to set the cookie to all the path/page/directory then set path attribute to the cookie
-function setCookie(key, value, expiry) {
-    var expires = new Date();
-    expires.setTime(expires.getTime() + (expiry * 24 * 60 * 60 * 1000));
-    document.cookie = key + '=' + value + ';path=/' + ';expires=' + expires.toUTCString();
-}*/
+function setJWT(value) {
+    window.localStorage.setItem('access_token', value.access_token);
+}
 
 function getCookie(key) {
     var keyValue = document.cookie.match('(^|;) ?' + key + '=([^;]*)(;|$)');
@@ -40,3 +37,4 @@ function eraseCookie(key) {
     var keyValue = getCookie(key);
     setCookie(key, keyValue, '-1');
 }
+
diff --git a/jams-server/src/main/resources/webapp/js/identity-management.js b/jams-server/src/main/resources/webapp/js/identity-management.js
index ad02ef67c352ca3176c67f0b9e409c8912c72d85..b700e0196d0bbffd7cd12ae933021805a965bc67 100644
--- a/jams-server/src/main/resources/webapp/js/identity-management.js
+++ b/jams-server/src/main/resources/webapp/js/identity-management.js
@@ -27,11 +27,16 @@ $("#inputIdentityManagmentType").change(function () {
 // Embedded
 $("#HSQL-form").submit(function (event) {
     event.preventDefault();
-    var inputs = {
+    var authSource = {};
+    var settings = {
         "CN": "http://ns.jami.net"
     };
-    var data = inputs;
-    postParamaters(data);
+
+    authSource['type'] = 'LOCAL';
+    authSource['localAuthSettings'] = settings;
+    var data = authSource;
+    // post request
+    postParameters(data);
 });
 
 // LDAP
@@ -47,35 +52,56 @@ $("#AD-form").submit(function (event) {
 });
 
 function setLDAPParametersData(form) {
-  var inputs = {}
+  var authSource = {};
+  var settings = {};
   $.each(($(form).serializeArray()), function (i, field){
       if (field.name == 'useStartTLS')
-          inputs[field.name] = $.parseJSON(field.value);
+          settings[field.name] = $.parseJSON(field.value);
       else
-          inputs[field.name] = field.value;
+          settings[field.name] = field.value;
   });
-  var data = inputs;
+  // settings['usernameField'] = "uid";
+  // settings['realm'] = "savoirfairelinux";
+  settings['fieldMappings'] = {};
+    settings['fieldMappings']['givenName'] = "FirstName";
+    settings['fieldMappings']['sn'] = "LastName";
+    settings['fieldMappings']['jpegPhoto'] = "ProfilePicture";
+    settings['fieldMappings']['mail'] = "Email";
+    settings['fieldMappings']['telephoneNumber'] = "PhoneNumber";
+    settings['fieldMappings']['mobile'] = "MobileNumber";
+    settings['fieldMappings']['facsimileTelephoneNumber'] = "FaxNumber";
+    settings['fieldMappings']['extensionName'] = "PhoneNumberExtension";
+    settings['fieldMappings']['o'] = "Organization";
+  console.log(settings);
+
+  authSource['type'] = 'LDAP';
+  authSource['ldapSettings'] = settings;
+  var data = authSource;
   // post request
-  postParamaters(data);
+    postParameters(data);
 }
 
 function setADParametersData(form) {
-    var inputs = {}
+    var authSource = {};
+    var settings = {};
     $.each(($(form).serializeArray()), function (i, field){
         if (field.name == 'port')
-            inputs[field.name] = parseInt(field.value);
+            settings[field.name] = parseInt(field.value);
         else if (field.name == 'isSSL')
-            inputs[field.name] = $.parseJSON(field.value);
+            settings[field.name] = $.parseJSON(field.value);
         else
-            inputs[field.name] = field.value;
+            settings[field.name] = field.value;
     });
-    var data = inputs;
+
+    authSource['type'] = 'AD';
+    authSource['activeDirectorySettings'] = settings;
+    var data = authSource;
     // post request
-    postParamaters(data);
+    postParameters(data);
 }
 
 // send post request
-function postParamaters(data) {
+function postParameters(data) {
   usePublicNS = $('#publicNS')[0].checked;
   var callback = set_installation_response("server-parameters.html" + "?usePublicNS=" + usePublicNS);
 
diff --git a/jams-server/src/main/resources/webapp/js/lib/countrySelect.min.js b/jams-server/src/main/resources/webapp/js/lib/countrySelect.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..34a537bcccaacc6a4f1ea0798e3e4ada6105bea0
--- /dev/null
+++ b/jams-server/src/main/resources/webapp/js/lib/countrySelect.min.js
@@ -0,0 +1 @@
+!function(n){"function"==typeof define&&define.amd?define(["jquery"],function(i){n(i,window,document)}):"object"==typeof module&&module.exports?module.exports=n(require("jquery"),window,document):n(jQuery,window,document)}(function(n,i,t,e){"use strict";var a="countrySelect",s=1,o={defaultCountry:"",defaultStyling:"inside",excludeCountries:[],onlyCountries:[],preferredCountries:["us","gb"],responsiveDropdown:n(i).width()<768},r=38,u=40,l=13,h=27,c=8,d=32,p=65,y=90;function f(i,t){this.element=i,this.options=n.extend({},o,t),this._defaults=o,this.ns="."+a+s++,this._name=a,this.init()}n(i).on("load",function(){!0}),f.prototype={init:function(){return this._processCountryData(),this._generateMarkup(),this._setInitialState(),this._initListeners(),this.autoCountryDeferred=new n.Deferred,this._initAutoCountry(),this.typedLetters="",this.autoCountryDeferred},_processCountryData:function(){this._setInstanceCountryData(),this._setPreferredCountries()},_setInstanceCountryData:function(){var i=this;if(this.options.onlyCountries.length){var t=[];n.each(this.options.onlyCountries,function(n,e){var a=i._getCountryData(e,!0);a&&t.push(a)}),this.countries=t}else if(this.options.excludeCountries.length){var e=this.options.excludeCountries.map(function(n){return n.toLowerCase()});this.countries=g.filter(function(n){return-1===e.indexOf(n.iso2)})}else this.countries=g},_setPreferredCountries:function(){var i=this;this.preferredCountries=[],n.each(this.options.preferredCountries,function(n,t){var e=i._getCountryData(t,!1);e&&i.preferredCountries.push(e)})},_generateMarkup:function(){this.countryInput=n(this.element);var t="country-select";this.options.defaultStyling&&(t+=" "+this.options.defaultStyling),this.countryInput.wrap(n("<div>",{class:t}));var e=n("<div>",{class:"flag-dropdown"}).insertAfter(this.countryInput),a=n("<div>",{class:"selected-flag"}).appendTo(e);this.selectedFlagInner=n("<div>",{class:"flag"}).appendTo(a),n("<div>",{class:"arrow"}).appendTo(a),this.countryList=n("<ul>",{class:"country-list v-hide"}).appendTo(e),this.preferredCountries.length&&(this._appendListItems(this.preferredCountries,"preferred"),n("<li>",{class:"divider"}).appendTo(this.countryList)),this._appendListItems(this.countries,""),this.countryCodeInput=n("#"+this.countryInput.attr("id")+"_code"),this.countryCodeInput||(this.countryCodeInput=n('<input type="hidden" id="'+this.countryInput.attr("id")+'_code" name="'+this.countryInput.attr("name")+'_code" value="" />'),this.countryCodeInput.insertAfter(this.countryInput)),this.dropdownHeight=this.countryList.outerHeight(),this.options.responsiveDropdown&&n(i).resize(function(){n(".country-select").each(function(){var i=this.offsetWidth;n(this).find(".country-list").css("width",i+"px")})}).resize(),this.countryList.removeClass("v-hide").addClass("hide"),this.countryListItems=this.countryList.children(".country")},_appendListItems:function(i,t){var e="";n.each(i,function(n,i){e+='<li class="country '+t+'" data-country-code="'+i.iso2+'">',e+='<div class="flag '+i.iso2+'"></div>',e+='<span class="country-name">'+i.name+"</span>",e+="</li>"}),this.countryList.append(e)},_setInitialState:function(){var n=!1;this.countryInput.val()&&(n=this._updateFlagFromInputVal());var i,t=this.countryCodeInput.val();(t&&this.selectCountry(t),n)||(this.options.defaultCountry&&(i=this._getCountryData(this.options.defaultCountry,!1))||(i=this.preferredCountries.length?this.preferredCountries[0]:this.countries[0]),this.defaultCountry=i.iso2)},_initListeners:function(){var n=this;this.countryInput.on("keyup"+this.ns,function(){n._updateFlagFromInputVal()}),this.selectedFlagInner.parent().on("click"+this.ns,function(i){n.countryList.hasClass("hide")&&!n.countryInput.prop("disabled")&&n._showDropdown()}),this.countryInput.on("blur"+this.ns,function(){n.countryInput.val()!=n.getSelectedCountryData().name&&n.setCountry(n.countryInput.val()),n.countryInput.val(n.getSelectedCountryData().name)})},_initAutoCountry:function(){"auto"===this.options.initialCountry?this._loadAutoCountry():(this.defaultCountry&&this.selectCountry(this.defaultCountry),this.autoCountryDeferred.resolve())},_loadAutoCountry:function(){n.fn[a].autoCountry?this.handleAutoCountry():n.fn[a].startedLoadingAutoCountry||(n.fn[a].startedLoadingAutoCountry=!0,"function"==typeof this.options.geoIpLookup&&this.options.geoIpLookup(function(i){n.fn[a].autoCountry=i.toLowerCase(),setTimeout(function(){n(".country-select input").countrySelect("handleAutoCountry")})}))},_focus:function(){this.countryInput.focus();var n=this.countryInput[0];if(n.setSelectionRange){var i=this.countryInput.val().length;n.setSelectionRange(i,i)}},_showDropdown:function(){this._setDropdownPosition();var n=this.countryList.children(".active");this._highlightListItem(n),this.countryList.removeClass("hide"),this._scrollTo(n),this._bindDropdownListeners(),this.selectedFlagInner.parent().children(".arrow").addClass("up")},_setDropdownPosition:function(){var t=this.countryInput.offset().top,e=n(i).scrollTop(),a=t+this.countryInput.outerHeight()+this.dropdownHeight<e+n(i).height(),s=t-this.dropdownHeight>e,o=!a&&s?"-"+(this.dropdownHeight-1)+"px":"";this.countryList.css("top",o)},_bindDropdownListeners:function(){var i=this;this.countryList.on("mouseover"+this.ns,".country",function(t){i._highlightListItem(n(this))}),this.countryList.on("click"+this.ns,".country",function(t){i._selectListItem(n(this))});var e=!0;n("html").on("click"+this.ns,function(n){n.preventDefault(),e||i._closeDropdown(),e=!1}),n(t).on("keydown"+this.ns,function(n){n.preventDefault(),n.which==r||n.which==u?i._handleUpDownKey(n.which):n.which==l?i._handleEnterKey():n.which==h?i._closeDropdown():n.which>=p&&n.which<=y||n.which===d?(i.typedLetters+=String.fromCharCode(n.which),i._filterCountries(i.typedLetters)):n.which===c&&(i.typedLetters=i.typedLetters.slice(0,-1),i._filterCountries(i.typedLetters))})},_handleUpDownKey:function(n){var i=this.countryList.children(".highlight").first(),t=n==r?i.prev():i.next();t.length&&(t.hasClass("divider")&&(t=n==r?t.prev():t.next()),this._highlightListItem(t),this._scrollTo(t))},_handleEnterKey:function(){var n=this.countryList.children(".highlight").first();n.length&&this._selectListItem(n)},_filterCountries:function(i){var t=this.countryListItems.filter(function(){return 0===n(this).text().toUpperCase().indexOf(i)&&!n(this).hasClass("preferred")});if(t.length){var e,a=t.filter(".highlight").first();e=a&&a.next()&&0===a.next().text().toUpperCase().indexOf(i)?a.next():t.first(),this._highlightListItem(e),this._scrollTo(e)}},_updateFlagFromInputVal:function(){var i=this,t=this.countryInput.val().replace(/(?=[() ])/g,"\\");if(t){for(var e=[],a=new RegExp("^"+t,"i"),s=0;s<this.countries.length;s++)this.countries[s].name.match(a)&&e.push(this.countries[s].iso2);var o=!1;return n.each(e,function(n,t){i.selectedFlagInner.hasClass(t)&&(o=!0)}),o||(this._selectFlag(e[0]),this.countryCodeInput.val(e[0]).trigger("change")),!0}return!1},_highlightListItem:function(n){this.countryListItems.removeClass("highlight"),n.addClass("highlight")},_getCountryData:function(n,i){for(var t=i?g:this.countries,e=0;e<t.length;e++)if(t[e].iso2==n)return t[e];return null},_selectFlag:function(n){if(!n)return!1;this.selectedFlagInner.attr("class","flag "+n);var i=this._getCountryData(n);this.selectedFlagInner.parent().attr("title",i.name);var t=this.countryListItems.children(".flag."+n).first().parent();this.countryListItems.removeClass("active"),t.addClass("active")},_selectListItem:function(n){var i=n.attr("data-country-code");this._selectFlag(i),this._closeDropdown(),this._updateName(i),this.countryInput.trigger("change"),this.countryCodeInput.trigger("change"),this._focus()},_closeDropdown:function(){this.countryList.addClass("hide"),this.selectedFlagInner.parent().children(".arrow").removeClass("up"),n(t).off("keydown"+this.ns),n("html").off("click"+this.ns),this.countryList.off(this.ns),this.typedLetters=""},_scrollTo:function(n){if(n&&n.offset()){var i=this.countryList,t=i.height(),e=i.offset().top,a=e+t,s=n.outerHeight(),o=n.offset().top,r=o+s,u=o-e+i.scrollTop();if(o<e)i.scrollTop(u);else if(r>a){var l=t-s;i.scrollTop(u-l)}}},_updateName:function(n){this.countryCodeInput.val(n).trigger("change"),this.countryInput.val(this._getCountryData(n).name)},handleAutoCountry:function(){"auto"===this.options.initialCountry&&(this.defaultCountry=n.fn[a].autoCountry,this.countryInput.val()||this.selectCountry(this.defaultCountry),this.autoCountryDeferred.resolve())},getSelectedCountryData:function(){var n=this.selectedFlagInner.attr("class").split(" ")[1];return this._getCountryData(n)},selectCountry:function(n){n=n.toLowerCase(),this.selectedFlagInner.hasClass(n)||(this._selectFlag(n),this._updateName(n))},setCountry:function(n){this.countryInput.val(n),this._updateFlagFromInputVal()},destroy:function(){this.countryInput.off(this.ns),this.selectedFlagInner.parent().off(this.ns),this.countryInput.parent().before(this.countryInput).remove()}},n.fn[a]=function(i){var t,s=arguments;return i===e||"object"==typeof i?this.each(function(){n.data(this,"plugin_"+a)||n.data(this,"plugin_"+a,new f(this,i))}):"string"==typeof i&&"_"!==i[0]&&"init"!==i?(this.each(function(){var e=n.data(this,"plugin_"+a);e instanceof f&&"function"==typeof e[i]&&(t=e[i].apply(e,Array.prototype.slice.call(s,1))),"destroy"===i&&n.data(this,"plugin_"+a,null)}),t!==e?t:this):void 0},n.fn[a].getCountryData=function(){return g},n.fn[a].setCountryData=function(n){g=n};var g=n.each([{n:"Afghanistan (‫افغانستان‬‎)",i:"af"},{n:"Åland Islands (Åland)",i:"ax"},{n:"Albania (Shqipëri)",i:"al"},{n:"Algeria (‫الجزائر‬‎)",i:"dz"},{n:"American Samoa",i:"as"},{n:"Andorra",i:"ad"},{n:"Angola",i:"ao"},{n:"Anguilla",i:"ai"},{n:"Antigua and Barbuda",i:"ag"},{n:"Argentina",i:"ar"},{n:"Armenia (Հայաստան)",i:"am"},{n:"Aruba",i:"aw"},{n:"Australia",i:"au"},{n:"Austria (Österreich)",i:"at"},{n:"Azerbaijan (Azərbaycan)",i:"az"},{n:"Bahamas",i:"bs"},{n:"Bahrain (‫البحرين‬‎)",i:"bh"},{n:"Bangladesh (বাংলাদেশ)",i:"bd"},{n:"Barbados",i:"bb"},{n:"Belarus (Беларусь)",i:"by"},{n:"Belgium (België)",i:"be"},{n:"Belize",i:"bz"},{n:"Benin (Bénin)",i:"bj"},{n:"Bermuda",i:"bm"},{n:"Bhutan (འབྲུག)",i:"bt"},{n:"Bolivia",i:"bo"},{n:"Bosnia and Herzegovina (Босна и Херцеговина)",i:"ba"},{n:"Botswana",i:"bw"},{n:"Brazil (Brasil)",i:"br"},{n:"British Indian Ocean Territory",i:"io"},{n:"British Virgin Islands",i:"vg"},{n:"Brunei",i:"bn"},{n:"Bulgaria (България)",i:"bg"},{n:"Burkina Faso",i:"bf"},{n:"Burundi (Uburundi)",i:"bi"},{n:"Cambodia (កម្ពុជា)",i:"kh"},{n:"Cameroon (Cameroun)",i:"cm"},{n:"Canada",i:"ca"},{n:"Cape Verde (Kabu Verdi)",i:"cv"},{n:"Caribbean Netherlands",i:"bq"},{n:"Cayman Islands",i:"ky"},{n:"Central African Republic (République Centrafricaine)",i:"cf"},{n:"Chad (Tchad)",i:"td"},{n:"Chile",i:"cl"},{n:"China (中国)",i:"cn"},{n:"Christmas Island",i:"cx"},{n:"Cocos (Keeling) Islands (Kepulauan Cocos (Keeling))",i:"cc"},{n:"Colombia",i:"co"},{n:"Comoros (‫جزر القمر‬‎)",i:"km"},{n:"Congo (DRC) (Jamhuri ya Kidemokrasia ya Kongo)",i:"cd"},{n:"Congo (Republic) (Congo-Brazzaville)",i:"cg"},{n:"Cook Islands",i:"ck"},{n:"Costa Rica",i:"cr"},{n:"Côte d’Ivoire",i:"ci"},{n:"Croatia (Hrvatska)",i:"hr"},{n:"Cuba",i:"cu"},{n:"Curaçao",i:"cw"},{n:"Cyprus (Κύπρος)",i:"cy"},{n:"Czech Republic (Česká republika)",i:"cz"},{n:"Denmark (Danmark)",i:"dk"},{n:"Djibouti",i:"dj"},{n:"Dominica",i:"dm"},{n:"Dominican Republic (República Dominicana)",i:"do"},{n:"Ecuador",i:"ec"},{n:"Egypt (‫مصر‬‎)",i:"eg"},{n:"El Salvador",i:"sv"},{n:"Equatorial Guinea (Guinea Ecuatorial)",i:"gq"},{n:"Eritrea",i:"er"},{n:"Estonia (Eesti)",i:"ee"},{n:"Ethiopia",i:"et"},{n:"Falkland Islands (Islas Malvinas)",i:"fk"},{n:"Faroe Islands (Føroyar)",i:"fo"},{n:"Fiji",i:"fj"},{n:"Finland (Suomi)",i:"fi"},{n:"France",i:"fr"},{n:"French Guiana (Guyane française)",i:"gf"},{n:"French Polynesia (Polynésie française)",i:"pf"},{n:"Gabon",i:"ga"},{n:"Gambia",i:"gm"},{n:"Georgia (საქართველო)",i:"ge"},{n:"Germany (Deutschland)",i:"de"},{n:"Ghana (Gaana)",i:"gh"},{n:"Gibraltar",i:"gi"},{n:"Greece (Ελλάδα)",i:"gr"},{n:"Greenland (Kalaallit Nunaat)",i:"gl"},{n:"Grenada",i:"gd"},{n:"Guadeloupe",i:"gp"},{n:"Guam",i:"gu"},{n:"Guatemala",i:"gt"},{n:"Guernsey",i:"gg"},{n:"Guinea (Guinée)",i:"gn"},{n:"Guinea-Bissau (Guiné Bissau)",i:"gw"},{n:"Guyana",i:"gy"},{n:"Haiti",i:"ht"},{n:"Honduras",i:"hn"},{n:"Hong Kong (香港)",i:"hk"},{n:"Hungary (Magyarország)",i:"hu"},{n:"Iceland (Ísland)",i:"is"},{n:"India (भारत)",i:"in"},{n:"Indonesia",i:"id"},{n:"Iran (‫ایران‬‎)",i:"ir"},{n:"Iraq (‫العراق‬‎)",i:"iq"},{n:"Ireland",i:"ie"},{n:"Isle of Man",i:"im"},{n:"Israel (‫ישראל‬‎)",i:"il"},{n:"Italy (Italia)",i:"it"},{n:"Jamaica",i:"jm"},{n:"Japan (日本)",i:"jp"},{n:"Jersey",i:"je"},{n:"Jordan (‫الأردن‬‎)",i:"jo"},{n:"Kazakhstan (Казахстан)",i:"kz"},{n:"Kenya",i:"ke"},{n:"Kiribati",i:"ki"},{n:"Kosovo (Kosovë)",i:"xk"},{n:"Kuwait (‫الكويت‬‎)",i:"kw"},{n:"Kyrgyzstan (Кыргызстан)",i:"kg"},{n:"Laos (ລາວ)",i:"la"},{n:"Latvia (Latvija)",i:"lv"},{n:"Lebanon (‫لبنان‬‎)",i:"lb"},{n:"Lesotho",i:"ls"},{n:"Liberia",i:"lr"},{n:"Libya (‫ليبيا‬‎)",i:"ly"},{n:"Liechtenstein",i:"li"},{n:"Lithuania (Lietuva)",i:"lt"},{n:"Luxembourg",i:"lu"},{n:"Macau (澳門)",i:"mo"},{n:"Macedonia (FYROM) (Македонија)",i:"mk"},{n:"Madagascar (Madagasikara)",i:"mg"},{n:"Malawi",i:"mw"},{n:"Malaysia",i:"my"},{n:"Maldives",i:"mv"},{n:"Mali",i:"ml"},{n:"Malta",i:"mt"},{n:"Marshall Islands",i:"mh"},{n:"Martinique",i:"mq"},{n:"Mauritania (‫موريتانيا‬‎)",i:"mr"},{n:"Mauritius (Moris)",i:"mu"},{n:"Mayotte",i:"yt"},{n:"Mexico (México)",i:"mx"},{n:"Micronesia",i:"fm"},{n:"Moldova (Republica Moldova)",i:"md"},{n:"Monaco",i:"mc"},{n:"Mongolia (Монгол)",i:"mn"},{n:"Montenegro (Crna Gora)",i:"me"},{n:"Montserrat",i:"ms"},{n:"Morocco (‫المغرب‬‎)",i:"ma"},{n:"Mozambique (Moçambique)",i:"mz"},{n:"Myanmar (Burma) (မြန်မာ)",i:"mm"},{n:"Namibia (Namibië)",i:"na"},{n:"Nauru",i:"nr"},{n:"Nepal (नेपाल)",i:"np"},{n:"Netherlands (Nederland)",i:"nl"},{n:"New Caledonia (Nouvelle-Calédonie)",i:"nc"},{n:"New Zealand",i:"nz"},{n:"Nicaragua",i:"ni"},{n:"Niger (Nijar)",i:"ne"},{n:"Nigeria",i:"ng"},{n:"Niue",i:"nu"},{n:"Norfolk Island",i:"nf"},{n:"North Korea (조선 민주주의 인민 공화국)",i:"kp"},{n:"Northern Mariana Islands",i:"mp"},{n:"Norway (Norge)",i:"no"},{n:"Oman (‫عُمان‬‎)",i:"om"},{n:"Pakistan (‫پاکستان‬‎)",i:"pk"},{n:"Palau",i:"pw"},{n:"Palestine (‫فلسطين‬‎)",i:"ps"},{n:"Panama (Panamá)",i:"pa"},{n:"Papua New Guinea",i:"pg"},{n:"Paraguay",i:"py"},{n:"Peru (Perú)",i:"pe"},{n:"Philippines",i:"ph"},{n:"Pitcairn Islands",i:"pn"},{n:"Poland (Polska)",i:"pl"},{n:"Portugal",i:"pt"},{n:"Puerto Rico",i:"pr"},{n:"Qatar (‫قطر‬‎)",i:"qa"},{n:"Réunion (La Réunion)",i:"re"},{n:"Romania (România)",i:"ro"},{n:"Russia (Россия)",i:"ru"},{n:"Rwanda",i:"rw"},{n:"Saint Barthélemy (Saint-Barthélemy)",i:"bl"},{n:"Saint Helena",i:"sh"},{n:"Saint Kitts and Nevis",i:"kn"},{n:"Saint Lucia",i:"lc"},{n:"Saint Martin (Saint-Martin (partie française))",i:"mf"},{n:"Saint Pierre and Miquelon (Saint-Pierre-et-Miquelon)",i:"pm"},{n:"Saint Vincent and the Grenadines",i:"vc"},{n:"Samoa",i:"ws"},{n:"San Marino",i:"sm"},{n:"São Tomé and Príncipe (São Tomé e Príncipe)",i:"st"},{n:"Saudi Arabia (‫المملكة العربية السعودية‬‎)",i:"sa"},{n:"Senegal (Sénégal)",i:"sn"},{n:"Serbia (Србија)",i:"rs"},{n:"Seychelles",i:"sc"},{n:"Sierra Leone",i:"sl"},{n:"Singapore",i:"sg"},{n:"Sint Maarten",i:"sx"},{n:"Slovakia (Slovensko)",i:"sk"},{n:"Slovenia (Slovenija)",i:"si"},{n:"Solomon Islands",i:"sb"},{n:"Somalia (Soomaaliya)",i:"so"},{n:"South Africa",i:"za"},{n:"South Georgia & South Sandwich Islands",i:"gs"},{n:"South Korea (대한민국)",i:"kr"},{n:"South Sudan (‫جنوب السودان‬‎)",i:"ss"},{n:"Spain (España)",i:"es"},{n:"Sri Lanka (ශ්‍රී ලංකාව)",i:"lk"},{n:"Sudan (‫السودان‬‎)",i:"sd"},{n:"Suriname",i:"sr"},{n:"Svalbard and Jan Mayen (Svalbard og Jan Mayen)",i:"sj"},{n:"Swaziland",i:"sz"},{n:"Sweden (Sverige)",i:"se"},{n:"Switzerland (Schweiz)",i:"ch"},{n:"Syria (‫سوريا‬‎)",i:"sy"},{n:"Taiwan (台灣)",i:"tw"},{n:"Tajikistan",i:"tj"},{n:"Tanzania",i:"tz"},{n:"Thailand (ไทย)",i:"th"},{n:"Timor-Leste",i:"tl"},{n:"Togo",i:"tg"},{n:"Tokelau",i:"tk"},{n:"Tonga",i:"to"},{n:"Trinidad and Tobago",i:"tt"},{n:"Tunisia (‫تونس‬‎)",i:"tn"},{n:"Turkey (Türkiye)",i:"tr"},{n:"Turkmenistan",i:"tm"},{n:"Turks and Caicos Islands",i:"tc"},{n:"Tuvalu",i:"tv"},{n:"Uganda",i:"ug"},{n:"Ukraine (Україна)",i:"ua"},{n:"United Arab Emirates (‫الإمارات العربية المتحدة‬‎)",i:"ae"},{n:"United Kingdom",i:"gb"},{n:"United States",i:"us"},{n:"U.S. Minor Outlying Islands",i:"um"},{n:"U.S. Virgin Islands",i:"vi"},{n:"Uruguay",i:"uy"},{n:"Uzbekistan (Oʻzbekiston)",i:"uz"},{n:"Vanuatu",i:"vu"},{n:"Vatican City (Città del Vaticano)",i:"va"},{n:"Venezuela",i:"ve"},{n:"Vietnam (Việt Nam)",i:"vn"},{n:"Wallis and Futuna",i:"wf"},{n:"Western Sahara (‫الصحراء الغربية‬‎)",i:"eh"},{n:"Yemen (‫اليمن‬‎)",i:"ye"},{n:"Zambia",i:"zm"},{n:"Zimbabwe",i:"zw"}],function(n,i){i.name=i.n,i.iso2=i.i,delete i.n,delete i.i})});
\ No newline at end of file
diff --git a/jams-server/src/main/resources/webapp/js/new-password.js b/jams-server/src/main/resources/webapp/js/new-password.js
index a659dfe49bf7f9bd5a966c980a1fbb68d3aa453d..9e0c33b0e63f3a6474d3ad83093a9f64d9553e50 100644
--- a/jams-server/src/main/resources/webapp/js/new-password.js
+++ b/jams-server/src/main/resources/webapp/js/new-password.js
@@ -30,8 +30,6 @@ document.getElementById("changePasswordButton").addEventListener('click', functi
     var inputConfirmPassword = $('#inputConfirmPassword').val();
     var oldPassword = $('#inputCurrentPassword').val();
     var username = window.location.href.substring(window.location.href.indexOf("=") + 1, window.location.href.length);
-    console.log(username);
-
 
     // In theory we already have the username and we shouldn't be able to change it.
     jsonData = {
@@ -45,9 +43,6 @@ document.getElementById("changePasswordButton").addEventListener('click', functi
         "oldPassword": oldPassword
     }
 
-    console.log(jsonData);
-    console.log(credentials);
-
     // If password and confirmPassword not entered
     if (inputPassword == '' || inputConfirmPassword == '') {
     }
diff --git a/jams-server/src/main/resources/webapp/js/signup.js b/jams-server/src/main/resources/webapp/js/signup.js
index d8de999d5b3714356cf04fc8c468566f83fe7c67..d15fb96b65a163a1a6b5dc2d370cb89728e77c9f 100644
--- a/jams-server/src/main/resources/webapp/js/signup.js
+++ b/jams-server/src/main/resources/webapp/js/signup.js
@@ -24,6 +24,8 @@ var credentials = null;
 var date = new Date();
 var minutes = 15;
 
+checkAdminAccountStatus();
+checkAuthentication();
 
 $(".form-submit").click(function (event) {
   event.preventDefault();
@@ -56,7 +58,7 @@ $(".form-submit").click(function (event) {
           ajaxApiCall(api_path_post_auth_login, "POST", jsonData, null, signinCallBackHandler);
         }
         else {
-          ajaxApiCall(api_path_post_install_admin, "POST", jsonData, null, createAdminCallBackHandler);
+          ajaxApiCall(api_path_post_install_admin, "PUT", jsonData, null, createAdminCallBackHandler);
         }
       }
     }
@@ -82,12 +84,12 @@ $('#cancel-submit').click(function (event) {
 });
 
 function createAdminCallBackHandler(data, statusCode, jqXHR) {
-  if (jqXHR.status == 200 && data.token != 'null') {
-    date.setTime(date.getTime() + (minutes * 60 * 1000));
+    console.log(data);
+    console.log(statusCode);
+    console.log(jqXHR);
+  if (jqXHR.status == 200 && data.access_token != 'null') {
     // set username token
-    setCookie(keyUsername, jsonData['username'], { expires: date });
-    // set isAdmin token
-    setCookie(keyAdmin, true, { expires: date });
+    setJWT(data);
     window.location.replace("ca-setup.html");
   }
 }
diff --git a/jams-server/src/main/resources/webapp/pages/ca-setup.html b/jams-server/src/main/resources/webapp/templates/ca-setup.html
similarity index 100%
rename from jams-server/src/main/resources/webapp/pages/ca-setup.html
rename to jams-server/src/main/resources/webapp/templates/ca-setup.html
diff --git a/jams-server/src/main/resources/webapp/pages/config.html b/jams-server/src/main/resources/webapp/templates/config.html
similarity index 98%
rename from jams-server/src/main/resources/webapp/pages/config.html
rename to jams-server/src/main/resources/webapp/templates/config.html
index 9ac1afc1f22414d9e3f055513b8739300956820b..6057afdd33d2cfb5c3e12ac5b4872e251df9af5d 100644
--- a/jams-server/src/main/resources/webapp/pages/config.html
+++ b/jams-server/src/main/resources/webapp/templates/config.html
@@ -302,7 +302,7 @@
               <div class="form-label-group">
                 <div class="label-title">Server Address</div>
                 <div class="label-description"></div>
-                <input type="text" name="serverURI" class="form-control" required autocomplete="off" value=""/>
+                <input type="text" name="host" class="form-control" required autocomplete="off" value=""/>
               </div>
               <div class="form-label-group">
                 <div class="label-title">Administrator Username <i class="fa fa-info-circle" data-toggle="tooltip" data-placement="right" title="Please use LDAP convention (ex : cn=name, ou=unit, dc=domain)"></i></div>
@@ -324,7 +324,7 @@
                 <div class="label-description"></div>
                 <div class="select_wrapper-picker">
                   <select  name="usernameField" id="usernameField" class="selectpicker" required>
-                    <option value="uid=%s">UID</option>
+                    <option value="uid">UID</option>
                   </select>
                 </div>
               </div>
@@ -353,8 +353,8 @@
         <div data-name="useStartTLS"></div>
       </div>
       <div class="label-description d-flex">
-        <div class="mr-2" data-label="serverURI">Server Address:</div>
-        <div data-name="serverURI"></div>
+        <div class="mr-2" data-label="host">Server Address:</div>
+        <div data-name="host"></div>
       </div>
       <div class="label-description d-flex">
         <div class="mr-2" data-label="user">Administrator Username:</div>
diff --git a/jams-server/src/main/resources/webapp/templates/contacts.html b/jams-server/src/main/resources/webapp/templates/contacts.html
new file mode 100644
index 0000000000000000000000000000000000000000..a80f3e42c74c7dd17ba04803b23054bfa7909193
--- /dev/null
+++ b/jams-server/src/main/resources/webapp/templates/contacts.html
@@ -0,0 +1,101 @@
+<!-- /*
+ *     JAMS - Jami Account Management Server
+ *     Copyright (C) 2020 Savoir-faire Linux Inc.
+ *
+ *     This program is free software: you can redistribute it and/or modify
+ *     it under the terms of the GNU Affero General Public License as published by
+ *     the Free Software Foundation, either version 3 of the License, or
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU Affero General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Affero General Public License
+ *     along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */ -->
+
+<!DOCTYPE html>
+<html>
+<title>JAMS Client</title>
+<meta charset="UTF-8">
+<meta name="viewport"
+      content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<!--[if lt IE 9]>
+<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
+<![endif]-->
+<!--[if lt IE 9]>
+<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
+<![endif]-->
+<link rel="stylesheet" href="../css/bootstrap.css">
+<link rel="stylesheet" href="../css/font-awesome.min.css">
+<link rel="stylesheet" href="../css/aos.css">
+<link rel="stylesheet" href="../css/main.css">
+<script src="../js/lib/jquery.min.js" charset="utf-8"></script>
+<script src="../js/api.js"></script>
+<script src="../js/auth.js" charset="utf-8"></script>
+<script src="../js/cookies-manager.js" charset="utf-8"></script>
+<script>
+    $(function () {
+        $("#header").load("header.html");
+        $("#footer").load("footer.html");
+    });
+</script>
+<body>
+<div id="header" class="header"></div>
+<div class="spacer spacer--huge"></div>
+<div id="content">
+    <div class="contactsanddevices">
+        <div id="contactsDisplay" class="col-xl-2 col-lg-2 col-md-2 col-sm-2">
+            <table class="table-stripped">
+                <thead>
+                <th>My Contacts <button class="add-contact" title="Add Contact"><i class="fa fa-user-plus"></i></button><button class="maximizecontact" title="Contacts Details"><i class="fa fa-external-link"></i></button></th>
+                </thead>
+                <tbody class="contacts-results-container"></tbody>
+            </table>
+        </div>
+        <div id="devicesDisplay" class="col-xl-2 col-lg-2 col-md-2 col-sm-2">
+            <table class="table-stripped">
+                <thead>
+                <th>My Devices<button class="maximizedevices" title="Devices Details"><i class="fa fa-external-link"></i></button></th>
+                </thead>
+                <tbody class="devices-results-container"></tbody>
+            </table>
+        </div>
+    </div>
+    <div class="container" data-aos="fade-up">
+        <div class="row">
+            <div class="loading">Loading&#8230;</div>
+            <button class="add-contact" title="Add Contact"><i class="fa fa-user-plus"></i></button>
+            <div class="col-xl-12 col-lg-12 col-md-12 col-sm-12">
+                <div class="table_wrapper">
+                    <table class="table-full table-striped">
+                        <thead>
+                        <tr>
+                            <th>Username</th>
+                            <th>Type</th>
+                            <th>Phone Number</th>
+                            <th>Actions</th>
+                        </tr>
+                        </thead>
+                        <tbody class="contacts-results-container">
+                        <tr class="empty-results bubble"><td colspan="5" class="text-alert">No contacts found</td></tr>
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<div id="footer"></div>
+<script src="../js/lib/jquery.min.js" charset="utf-8"></script>
+<script src="../js/lib/popper.min.js" charset="utf-8"></script>
+<script src="../js/lib/bootstrap.min.js" charset="utf-8"></script>
+<script src="../js/lib/jquery.validate.min.js" charset="utf-8"></script>
+<script src="../js/lib/additional-methods.min.js" charset="utf-8"></script>
+<script src="../js/signup.js" charset="utf-8"></script>
+<script src="../js/password.js" charset="utf-8"></script>
+</body>
+</html>
diff --git a/jams-server/src/main/resources/webapp/templates/devices.html b/jams-server/src/main/resources/webapp/templates/devices.html
new file mode 100644
index 0000000000000000000000000000000000000000..ade006bc7a0874f5bd99d164f9ef59953ccc6f18
--- /dev/null
+++ b/jams-server/src/main/resources/webapp/templates/devices.html
@@ -0,0 +1,99 @@
+<!-- /*
+ *     JAMS - Jami Account Management Server
+ *     Copyright (C) 2020 Savoir-faire Linux Inc.
+ *
+ *     This program is free software: you can redistribute it and/or modify
+ *     it under the terms of the GNU Affero General Public License as published by
+ *     the Free Software Foundation, either version 3 of the License, or
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU Affero General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Affero General Public License
+ *     along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */ -->
+
+<!DOCTYPE html>
+<html>
+<title>JAMS Client</title>
+<meta charset="UTF-8">
+<meta name="viewport"
+      content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<!--[if lt IE 9]>
+<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
+<![endif]-->
+<!--[if lt IE 9]>
+<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
+<![endif]-->
+<link rel="stylesheet" href="../css/bootstrap.css">
+<link rel="stylesheet" href="../css/font-awesome.min.css">
+<link rel="stylesheet" href="../css/aos.css">
+<link rel="stylesheet" href="../css/main.css">
+<script src="../js/lib/jquery.min.js" charset="utf-8"></script>
+<script src="../js/api.js"></script>
+<script src="../js/auth.js" charset="utf-8"></script>
+<script src="../js/cookies-manager.js" charset="utf-8"></script>
+<script>
+    $(function () {
+        $("#header").load("header.html");
+        $("#footer").load("footer.html");
+    });
+</script>
+<body>
+<div id="header" class="header"></div>
+<div class="spacer spacer--huge"></div>
+<div id="content">
+    <div class="contactsanddevices">
+        <div id="contactsDisplay" class="col-xl-2 col-lg-2 col-md-2 col-sm-2">
+            <table class="table-stripped">
+                <thead>
+                <th>My Contacts <button class="add-contact" title="Add Contact"><i class="fa fa-user-plus"></i></button><button class="maximizecontact" title="Contacts Details"><i class="fa fa-external-link"></i></button></th>
+                </thead>
+                <tbody class="contacts-results-container"></tbody>
+            </table>
+        </div>
+        <div id="devicesDisplay" class="col-xl-2 col-lg-2 col-md-2 col-sm-2">
+            <table class="table-stripped">
+                <thead>
+                <th>My Devices<button class="maximizedevices" title="Devices Details"><i class="fa fa-external-link"></i></button></th>
+                </thead>
+                <tbody class="devices-results-container"></tbody>
+            </table>
+        </div>
+    </div>
+    <div class="container" data-aos="fade-up">
+        <div class="row">
+            <div class="loading">Loading&#8230;</div>
+            <div class="col-xl-12 col-lg-12 col-md-12 col-sm-12">
+                <div class="table_wrapper">
+                    <table class="table-full table-striped">
+                        <thead>
+                        <tr>
+                            <th>Device ID</th>
+                            <th>Device Name</th>
+                            <th>Creation Date</th>
+                            <th>Status</th>
+                            <th>Actions</th>
+                        </tr>
+                        </thead>
+                        <tbody class="devices-results-container"></tbody>
+                    </table>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<div id="footer"></div>
+<script src="../js/lib/jquery.min.js" charset="utf-8"></script>
+<script src="../js/lib/popper.min.js" charset="utf-8"></script>
+<script src="../js/lib/bootstrap.min.js" charset="utf-8"></script>
+<script src="../js/lib/jquery.validate.min.js" charset="utf-8"></script>
+<script src="../js/lib/additional-methods.min.js" charset="utf-8"></script>
+<script src="../js/signup.js" charset="utf-8"></script>
+<script src="../js/password.js" charset="utf-8"></script>
+</body>
+</html>
diff --git a/jams-server/src/main/resources/webapp/pages/footer.html b/jams-server/src/main/resources/webapp/templates/footer.html
similarity index 100%
rename from jams-server/src/main/resources/webapp/pages/footer.html
rename to jams-server/src/main/resources/webapp/templates/footer.html
diff --git a/jams-server/src/main/resources/webapp/pages/header.html b/jams-server/src/main/resources/webapp/templates/header.html
similarity index 100%
rename from jams-server/src/main/resources/webapp/pages/header.html
rename to jams-server/src/main/resources/webapp/templates/header.html
diff --git a/jams-server/src/main/resources/webapp/pages/identity-management.html b/jams-server/src/main/resources/webapp/templates/identity-management.html
similarity index 96%
rename from jams-server/src/main/resources/webapp/pages/identity-management.html
rename to jams-server/src/main/resources/webapp/templates/identity-management.html
index 4c01a6d6343f5cf3a9c5d0a5e9c54cf96a9ad7f2..d8a0d70b96f803b3da0f9c21b64d8aac2b6820ee 100644
--- a/jams-server/src/main/resources/webapp/pages/identity-management.html
+++ b/jams-server/src/main/resources/webapp/templates/identity-management.html
@@ -66,7 +66,7 @@
                         <select name="backendType" id="inputIdentityManagmentType" class="selectpicker" required>
                             <option value="LDAP-form">LDAP Server</option>
                             <option value="AD-form">Active Directory</option>
-                            <option value="HSQL-form">Local HSQL Database</option>
+                            <option value="HSQL-form">Local Derby Database</option>
                         </select>
                     </div>
                 </div>
@@ -85,12 +85,12 @@
                         <div class="form-label-group">
                             <div class="label-title">Server Address</div>
                             <div class="label-description"></div>
-                            <input type="text" name="serverURI" class="form-control" required autocomplete="off" value=""/>
+                            <input type="text" name="host" class="form-control" required autocomplete="off" value=""/>
                         </div>
                         <div class="form-label-group">
                             <div class="label-title">Administrator Username <i class="fa fa-info-circle" data-toggle="tooltip" data-placement="right" title="Please use LDAP convention (ex : cn=name, ou=unit, dc=domain)"></i></div>
                             <div class="label-description"></div>
-                            <input type="text" name="user" class="form-control" required autocomplete="off" value=""/>
+                            <input type="text" name="username" class="form-control" required autocomplete="off" value=""/>
                         </div>
                         <div class="form-label-group">
                             <div class="label-title">Password</div>
@@ -107,7 +107,7 @@
                             <div class="label-description"></div>
                             <div class="select_wrapper-picker">
                                 <select  name="usernameField" id="usernameField" class="selectpicker" required>
-                                    <option value="uid=%s">UID</option>
+                                    <option value="uid">UID</option>
                                 </select>
                             </div>
                         </div>
diff --git a/jams-server/src/main/resources/webapp/pages/login.jsp b/jams-server/src/main/resources/webapp/templates/login.jsp
similarity index 97%
rename from jams-server/src/main/resources/webapp/pages/login.jsp
rename to jams-server/src/main/resources/webapp/templates/login.jsp
index 077e7d6f1c47fff93f79c7976c4908edf2001511..bb09f83864e4d679b9a7aee33c7fcd0cfe38dcfc 100644
--- a/jams-server/src/main/resources/webapp/pages/login.jsp
+++ b/jams-server/src/main/resources/webapp/templates/login.jsp
@@ -39,8 +39,8 @@
   <script src="../js/lib/jquery.min.js" charset="utf-8"></script>
   <script>
     $(function () {
-      $("#header").load("/pages/header.html");
-      $("#footer").load("/pages/footer.html");
+      $("#header").load("/templates/header.html");
+      $("#footer").load("/templates/footer.html");
     });
   </script>
   <body>
diff --git a/jams-server/src/main/resources/webapp/pages/new-password.html b/jams-server/src/main/resources/webapp/templates/new-password.html
similarity index 100%
rename from jams-server/src/main/resources/webapp/pages/new-password.html
rename to jams-server/src/main/resources/webapp/templates/new-password.html
diff --git a/jams-server/src/main/resources/webapp/pages/search.html b/jams-server/src/main/resources/webapp/templates/search.html
similarity index 100%
rename from jams-server/src/main/resources/webapp/pages/search.html
rename to jams-server/src/main/resources/webapp/templates/search.html
diff --git a/jams-server/src/main/resources/webapp/pages/server-parameters.html b/jams-server/src/main/resources/webapp/templates/server-parameters.html
similarity index 100%
rename from jams-server/src/main/resources/webapp/pages/server-parameters.html
rename to jams-server/src/main/resources/webapp/templates/server-parameters.html
diff --git a/jams-server/src/main/resources/webapp/templates/signup.html b/jams-server/src/main/resources/webapp/templates/signup.html
new file mode 100644
index 0000000000000000000000000000000000000000..d80a112b709e7cbdefe6db016911aa425032c8cb
--- /dev/null
+++ b/jams-server/src/main/resources/webapp/templates/signup.html
@@ -0,0 +1,87 @@
+<!-- /*
+ *     JAMS - Jami Account Management Server
+ *     Copyright (C) 2019 Savoir-faire Linux Inc.
+ *
+ *     Author: Mohammed Raza <mohammed.raza@savoirfairelinux.com>
+ *
+ *     This program is free software: you can redistribute it and/or modify
+ *     it under the terms of the GNU Affero General Public License as published by
+ *     the Free Software Foundation, either version 3 of the License, or
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU Affero General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Affero General Public License
+ *     along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */ -->
+
+<!DOCTYPE html>
+<html>
+  <title>JAMS Client</title>
+  <meta charset="UTF-8">
+  <meta name="viewport"
+    content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <!--[if lt IE 9]>
+      <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
+    <![endif]-->
+  <!--[if lt IE 9]>
+      <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
+    <![endif]-->
+  <link rel="stylesheet" href="../css/bootstrap.css">
+  <link rel="stylesheet" href="../css/font-awesome.min.css">
+  <link rel="stylesheet" href="../css/aos.css">
+  <link rel="stylesheet" href="../css/main.css">
+  <script src="../js/lib/jquery.min.js" charset="utf-8"></script>
+  <script src="../js/api.js"></script>
+  <script src="../js/auth.js" charset="utf-8"></script>
+  <script src="../js/cookies-manager.js" charset="utf-8"></script>
+  <script>
+    $(function () {
+      $("#header").load("header.html");
+      $("#footer").load("footer.html");
+    });
+  </script>
+  <body>
+    <div id="header" class="header"></div>
+    <div class="spacer spacer--huge"></div>
+    <div id="content">
+      <div class="container" data-aos="fade-up">
+        <div class="row">
+          <div class="col-md-6 offset-md-3">
+            <form id="form-signup" class="d-none form-container">
+              <div class="form-label-group">
+                <div class="notification" style="display:none"><i class="fa fa-exclamation-circle" aria-hidden="true"></i>Cannot establish a connection with the API</div>
+                <div class="title"></div>
+                <div class="subtitle"></div>
+              </div>
+              <div class="form-label-group">
+                <label for="inputUsername" class="label-title">Username</label>
+                <input type="text" name="username" id="inputUsername" class="form-control" required autocomplete="off">
+              </div>
+              <div class="form-label-group">
+                <label for="inputPassword" class="label-title">Password</label>
+                <input type="password" name="password" id="inputPassword" class="form-control" required autocomplete="off">
+                <div class="progress" id="admin-password-progress-bar-container" style="display:none" >
+                  <div class="progress-bar" id="admin-password-progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:0%"></div>
+                </div>
+              </div>
+              <input class="btn btn-lg btn-primary btn-block form-submit" type="submit">
+            </form>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div id="footer"></div>
+    <script src="../js/lib/jquery.min.js" charset="utf-8"></script>
+    <script src="../js/lib/popper.min.js" charset="utf-8"></script>
+    <script src="../js/lib/bootstrap.min.js" charset="utf-8"></script>
+    <script src="../js/lib/jquery.validate.min.js" charset="utf-8"></script>
+    <script src="../js/lib/additional-methods.min.js" charset="utf-8"></script>
+    <script src="../js/signup.js" charset="utf-8"></script>
+    <script src="../js/password.js" charset="utf-8"></script>
+  </body>
+</html>
diff --git a/jams-server/src/main/resources/webapp/pages/user.html b/jams-server/src/main/resources/webapp/templates/user.html
similarity index 100%
rename from jams-server/src/main/resources/webapp/pages/user.html
rename to jams-server/src/main/resources/webapp/templates/user.html
diff --git a/pom.xml b/pom.xml
index bfce65ea3968cfd9cd76275c90dbee30ac8a3d8d..c50c937d7a9f2068e7d22430628e2e1e3b817b2f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,7 +34,7 @@
         <lombok.version>1.18.12</lombok.version>
         <log4j.version>1.7.30</log4j.version>
         <jupiter.api.version>5.7.0-M1</jupiter.api.version>
-        <tomcat.version>9.0.35</tomcat.version>
+        <tomcat.version>10.0.0-M5</tomcat.version>
         <map.struct.version>1.3.0.Final</map.struct.version>
         <maven.surefire.version>2.19.1</maven.surefire.version>
         <junit.surefire.version>1.1.0</junit.surefire.version>
@@ -54,6 +54,7 @@
         <maven.model.version>3.2.5</maven.model.version>
         <apache.httpcore.version>4.4.12</apache.httpcore.version>
         <apache.httpclient.version>4.5.10</apache.httpclient.version>
+        <ez.vcard.version>0.10.6</ez.vcard.version>
     </properties>
 
     <dependencies>