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 b2e0308576caf97408fdfa7e1f8f98556221bd0d..4f3723d855a96f63d8e224ca8b854bc9048b77ff 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/UserDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/UserDao.java
@@ -59,17 +59,31 @@ public class UserDao extends AbstractDao<User> {
     @Override
     public boolean updateObject(StatementList update, StatementList constraints) {
 
+        if(update.getStatements().get(0).getColumn() == "certificate"){
+
+            SQLConnection connection = DataStore.connectionPool.getConnection();
+            try {
+                String certificate = update.getStatements().get(0).getValue();
+                String user = constraints.getStatements().get(0).getValue();
+                PreparedStatement ps = connection.getConnection().prepareStatement("UPDATE users SET certificate = ? WHERE username = ?");
+                ps.setString(1, certificate);
+                ps.setString(2, user);
+                return ps.executeUpdate() != 0;
+            } catch (Exception e) {
+                log.error("An error has occurred while trying to update a user certificate: " + e.toString());
+                return false;
+            } finally {
+                DataStore.connectionPool.returnConnection(connection);
+            }
+
+        }
+
         String pw = update.getStatements().get(0).getValue();
         String salt = "";
         if (update.getStatements().size() > 1)
             salt = update.getStatements().get(1).getValue();
 
         String user = constraints.getStatements().get(0).getValue();
-//        String pwReset = "false";
-//
-//        if (update.getStatements().size() > 1) {
-//            pwReset = update.getStatements().get(1).getValue();
-//        }
 
         SQLConnection connection = DataStore.connectionPool.getConnection();
 
@@ -78,12 +92,7 @@ public class UserDao extends AbstractDao<User> {
             ps.setString(1, pw);
             ps.setString(2, salt);
             ps.setString(3, user);
-//            ps.executeUpdate();
-//
-//            ps = connection.getConnection().prepareStatement("UPDATE users SET needsPasswordReset = ? WHERE username = ?");
-//            ps.setString(1, pwReset);
-//
-//            ps.setString(2, user);
+
             return ps.executeUpdate() != 0;
         } catch (Exception e) {
             log.error("An error has occurred while trying to update a user: " + e.toString());
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 ae4c229c3d80b6f17cfad1718564c34033823ead..8aad8af84676b28bcb91baee3a5f2e5a896c9778 100644
--- a/datastore/src/main/java/net/jami/datastore/main/DataStore.java
+++ b/datastore/src/main/java/net/jami/datastore/main/DataStore.java
@@ -42,12 +42,16 @@ import net.jami.jams.common.dao.connectivity.ConnectionPool;
 import net.jami.jams.common.objects.user.User;
 import net.jami.jams.common.objects.user.UserGroupMapping;
 import net.jami.jams.common.objects.user.UserProfile;
+import net.jami.jams.common.utils.X509Utils;
+
 import org.flywaydb.core.Flyway;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 
+import javax.swing.plaf.nimbus.State;
+
 @Getter
 @Setter
 public class DataStore implements AuthenticationSource {
@@ -161,6 +165,18 @@ public class DataStore implements AuthenticationSource {
         return userProfileDao.updateObject(update, null);
     }
 
+    public boolean updateUserCertificate(User user) {
+
+        StatementList update  = new StatementList();
+        StatementList constraints  = new StatementList();
+
+        update.addStatement(new StatementElement("certificate","=", X509Utils.getPEMStringFromCertificate(user.getCertificate()),""));
+
+        constraints.addStatement(new StatementElement("username","=", user.getUsername(),""));
+
+        return userDao.updateObject(update, constraints);
+    }
+
     @Override
     public boolean authenticate(String username, String password) {
         StatementList statementList = new StatementList();
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 00fb29f0f9237b375ce890e6615cb09038bfd3ca..317b1b0a3e10240361dc641dafe34fc67fa69f3f 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
@@ -97,6 +97,11 @@ public class JamsCA implements CertificateAuthority {
         return CertificateWorker.getSignedCertificate(user);
     }
 
+    @Override
+    public User getRefreshedCertificate(User user) {
+        return CertificateWorker.getRefreshedCertificate(user);
+    }
+
     @Override
     public Device getSignedCertificate(User user, Device device) {
         return CertificateWorker.getSignedCertificate(user, device);
diff --git a/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/CertificateWorker.java b/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/CertificateWorker.java
index 20211087fbd8e97be6af5f728bdbb0c98d136ade..845ac79326dac47e1007695724382ff95edf956b 100644
--- a/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/CertificateWorker.java
+++ b/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/CertificateWorker.java
@@ -48,6 +48,10 @@ public class CertificateWorker {
         return UserBuilder.generateUser(user);
     }
 
+    public static User getRefreshedCertificate(User user){
+        return UserBuilder.refreshUser(user);
+    }
+
     public static Device getSignedCertificate(User user, Device device){
         return DeviceBuilder.generateDevice(user,device);
     }
diff --git a/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/DeviceBuilder.java b/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/DeviceBuilder.java
index d5c470b4540e593f66bbd56d00f1362a73eb152d..8f54fdce131471237204622a1ea2e6a097a83bf2 100644
--- a/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/DeviceBuilder.java
+++ b/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/DeviceBuilder.java
@@ -52,11 +52,12 @@ public class DeviceBuilder {
 
     public static Device generateDevice(User user, Device device){
         try {
+            long now = System.currentTimeMillis();
             X509v3CertificateBuilder builder = new X509v3CertificateBuilder(
                     new JcaX509CertificateHolder(user.getCertificate()).getSubject(),
                     new BigInteger(256, new SecureRandom()),
-                    new Date(System.currentTimeMillis() - SHIFT),
-                    new Date(System.currentTimeMillis() + JamsCA.deviceLifetime),
+                    new Date(now - SHIFT),
+                    new Date(now + JamsCA.deviceLifetime),
                     device.getCertificationRequest().getSubject(),
                     device.getCertificationRequest().getSubjectPublicKeyInfo()
             );
diff --git a/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/UserBuilder.java b/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/UserBuilder.java
index 6570601bb556d0c72c05c111c815303340e9f966..7da79d586193f49cb1686ba41515edb040e11d83 100644
--- a/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/UserBuilder.java
+++ b/jams-ca/src/main/java/net/jami/jams/ca/workers/csr/builders/UserBuilder.java
@@ -35,34 +35,66 @@ import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
 import java.math.BigInteger;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
+import java.security.MessageDigest;
 import java.security.SecureRandom;
 import java.util.Date;
 
 import static net.jami.jams.ca.workers.csr.CertificateWorker.SHIFT;
 
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.codec.digest.MessageDigestAlgorithms;
+
+
 @Slf4j
 public class UserBuilder {
 
     public static User generateUser(User user) {
         try {
+            long now = System.currentTimeMillis();
             KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
             keyPairGenerator.initialize(4096);
             KeyPair keyPair = keyPairGenerator.generateKeyPair();
             X509v3CertificateBuilder builder = new X509v3CertificateBuilder(
                     new JcaX509CertificateHolder(JamsCA.CA.getCertificate()).getSubject(),
-                    new BigInteger(256, new SecureRandom()),
-                    new Date(System.currentTimeMillis() - SHIFT),
-                    new Date(System.currentTimeMillis() + JamsCA.userLifetime),
+                    new BigInteger(128, new SecureRandom()),
+                    new Date(now - SHIFT),
+                    new Date(now + JamsCA.userLifetime),
                     new X500Name(user.getX509Fields().getDN()),
                     SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded())
             );
+
             user.setPrivateKey(keyPair.getPrivate());
             user.setCertificate(CertificateSigner.signCertificate(JamsCA.CA.getPrivateKey(), builder, ExtensionLibrary.userExtensions));
-
+            log.info("New user certificate:  Not valid after: " + user.getCertificate().getNotAfter());
             return user;
         } catch (Exception e) {
             log.error("Could not generate a user certificate: " + e.toString());
             return null;
         }
     }
+
+    public static User refreshUser(User user) {
+        return refreshUser(user, JamsCA.userLifetime);
+    }
+
+    public static User refreshUser(User user, long userLifeTime) {
+        try {
+            long now = System.currentTimeMillis();
+            X509v3CertificateBuilder builder = new X509v3CertificateBuilder(
+                    new JcaX509CertificateHolder(JamsCA.CA.getCertificate()).getSubject(),
+                    new BigInteger(128, new SecureRandom()),
+                    new Date(now - SHIFT),
+                    new Date(now + userLifeTime),
+                    new X500Name(user.getX509Fields().getDN()),
+                    new JcaX509CertificateHolder(user.getCertificate()).getSubjectPublicKeyInfo()
+            );
+            user.setCertificate(CertificateSigner.signCertificate(JamsCA.CA.getPrivateKey(), builder, ExtensionLibrary.userExtensions));
+            log.info("====> Refreshed user certificate:  Not valid after: " + user.getCertificate().getNotAfter());
+
+            return user;
+        } catch (Exception e) {
+            log.error("Could not refresh user certificate: " + e.toString());
+            return null;
+        }
+    }
 }
diff --git a/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/UserBuilderTest.java b/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/UserBuilderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..468a9b4ee5cb7e4652ceec3cc738fada07f18319
--- /dev/null
+++ b/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/UserBuilderTest.java
@@ -0,0 +1,80 @@
+package net.jami.jams.ca.workers.csr.builders;
+
+import net.jami.jams.ca.JamsCA;
+import lombok.extern.slf4j.Slf4j;
+
+import net.jami.jams.common.authentication.AuthenticationSourceType;
+import net.jami.jams.common.objects.roots.X509Fields;
+import net.jami.jams.common.objects.user.AccessLevel;
+import net.jami.jams.common.objects.user.User;
+import net.jami.jams.common.utils.X509Utils;
+import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Date;
+
+import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.Assertions;
+
+import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
+
+@Slf4j
+class UserBuilderTest {
+
+
+    @Test
+    void generateUserCertificate() {
+
+        User user = new User();
+        user.setUsername("TestUser");
+        user.setUserType(AuthenticationSourceType.LOCAL);
+        user.setX509Fields(new X509Fields());
+        user.getX509Fields().setCommonName("TestUser's Personal Certificate");
+        user = UserBuilder.generateUser(user);
+
+        Assertions.assertNotNull(user.getCertificate(),"User Certificate was not generated!");
+    }
+
+    @Test
+    void refreshUserCertificate() {
+
+        User user = new User();
+        user.setUsername("TestUser");
+        //user.setJamiId("");
+        user.setUserType(AuthenticationSourceType.LOCAL);
+        user.setX509Fields(new X509Fields());
+        user.getX509Fields().setCommonName("TestUser's Personal Certificate");
+        user = UserBuilder.generateUser(user);
+
+        Assertions.assertNotNull(user,"User was not generated!");
+
+        X509Certificate cert = user.getCertificate();
+        Assertions.assertNotNull(cert,"User Certificate was not generated!");
+
+        User refreshedUser = UserBuilder.refreshUser(user, 465_000_000);
+        Assertions.assertNotNull(refreshedUser,"User was not generated!");
+        X509Certificate new_cert = refreshedUser.getCertificate();
+
+        Assertions.assertArrayEquals(cert.getPublicKey().getEncoded(), new_cert.getPublicKey().getEncoded(), "PK is different");
+
+        Assertions.assertNotNull(new_cert,"User Certificate was not updated!");
+        Assertions.assertEquals(user.getAddress(), refreshedUser.getAddress(), "User address is different");
+
+        Assertions.assertNotEquals(cert.getNotAfter(), new_cert.getNotAfter());
+        try {
+            Assertions.assertEquals(new JcaX509CertificateHolder(cert).getSubjectPublicKeyInfo().getPublicKey(),
+                    new JcaX509CertificateHolder(new_cert).getSubjectPublicKeyInfo().getPublicKey());
+        } catch (Exception e) {
+            log.error("Error comparing two public keys information: ", e.getMessage());
+        }
+    }
+}
\ No newline at end of file
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 dfd933c124010a02e185d97be35d7aecb575b151..a8de02acd58ec763ca5235a1371d1b38b67b2f83 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
@@ -37,6 +37,7 @@ public interface CertificateAuthority {
     //Return a signed X509 certificate based on various constraints.
     void init(String settings, SystemAccount ca, SystemAccount ocsp);
     User getSignedCertificate(User user);
+    User getRefreshedCertificate(User user);
     Device getSignedCertificate(User user, Device device);
     SystemAccount getSignedCertificate(SystemAccount systemAccount);
     void revokeCertificate(RevocationRequest revocationRequest);