From 08e5e9686498e22db33260d55b304059ac1c3eaf Mon Sep 17 00:00:00 2001
From: Joze RIHTARSIC <joze.RIHTARSIC@ext.ec.europa.eu>
Date: Fri, 29 Apr 2022 10:12:40 +0200
Subject: [PATCH] Update alerts for credentials verification and suspension

---
 .../ui/enums/AlertSuspensionMomentEnum.java   |   6 +
 .../smp/data/ui/enums/AlertTypeEnum.java      |   8 +-
 .../smp/data/ui/enums/SMPPropertyEnum.java    |  34 +++--
 .../edelivery/smp/services/AlertService.java  |  92 ++++++++++----
 .../smp/services/ConfigurationService.java    |  76 ++++++++++--
 ...redentialVerificationFailedProperties.java |  11 ++
 ...als_expired.ftl => credential_expired.ftl} |   0
 ...ftl => credential_imminent_expiration.ftl} |   0
 ...suspended.ftl => credential_suspended.ftl} |   2 +-
 .../credential_verification_failed.ftl        | 117 ++++++++++++++++++
 .../smp/data/dao/AuditIntegrationTest.java    |   2 +-
 .../edelivery/smp/testutil/TestDBUtils.java   |   3 +-
 .../smp/auth/SMPAuthenticationProvider.java   |   9 +-
 .../auth/SMPAuthenticationProviderForUI.java  |  10 +-
 14 files changed, 318 insertions(+), 52 deletions(-)
 create mode 100644 smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/AlertSuspensionMomentEnum.java
 create mode 100644 smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/mail/prop/CredentialVerificationFailedProperties.java
 rename smp-server-library/src/main/resources/alert-mail-templates/{credentials_expired.ftl => credential_expired.ftl} (100%)
 rename smp-server-library/src/main/resources/alert-mail-templates/{credentials_imminent_expiration.ftl => credential_imminent_expiration.ftl} (100%)
 rename smp-server-library/src/main/resources/alert-mail-templates/{account_suspended.ftl => credential_suspended.ftl} (98%)
 create mode 100644 smp-server-library/src/main/resources/alert-mail-templates/credential_verification_failed.ftl

diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/AlertSuspensionMomentEnum.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/AlertSuspensionMomentEnum.java
new file mode 100644
index 000000000..85c208fdb
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/AlertSuspensionMomentEnum.java
@@ -0,0 +1,6 @@
+package eu.europa.ec.edelivery.smp.data.ui.enums;
+
+public enum AlertSuspensionMomentEnum {
+    AT_LOGON,
+    WHEN_BLOCKED
+}
\ No newline at end of file
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/AlertTypeEnum.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/AlertTypeEnum.java
index 1785ee7aa..426cb5bc9 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/AlertTypeEnum.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/AlertTypeEnum.java
@@ -8,12 +8,12 @@ package eu.europa.ec.edelivery.smp.data.ui.enums;
  */
 public enum AlertTypeEnum {
     TEST_ALERT("test_mail.ftl"),
-    CREDENTIALS_IMMINENT_EXPIRATION("credentials_imminent_expiration.ftl"),
-    CREDENTIALS_EXPIRED("credentials_expired.ftl"),
-    ACCOUNT_SUSPENDED("account_suspended.ftl"),
+    CREDENTIAL_IMMINENT_EXPIRATION("credential_imminent_expiration.ftl"),
+    CREDENTIAL_EXPIRED("credential_expired.ftl"),
+    CREDENTIAL_SUSPENDED("credential_suspended.ftl"),
+    CREDENTIAL_VERIFICATION_FAILED("credential_verification_failed.ftl"),
     ;
 
-
     private final String template;
 
     AlertTypeEnum(String template) {
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java
index 0e3dd9d46..8442ec4af 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java
@@ -117,6 +117,22 @@ public enum SMPPropertyEnum {
     MAIL_SERVER_PASSWORD("mail.smtp.password", "", "smtp mail protocol - encrypted password for submitting the emails.", false,true,false, STRING),
     MAIL_SERVER_PROPERTIES("mail.smtp.properties", "", " key:value properties separated with '|'.Ex: mail.smtp.auth:true|mail.smtp.starttls.enable:true|mail.smtp.quitwait:false.", false, false,false, MAP_STRING),
 
+    ALERT_USER_LOGIN_FAILURE_ENABLED("smp.alert.user.login_failure.enabled",
+            "false", "Enable/disable the login failure alert of the authentication module.", false, false,false, BOOLEAN),
+    ALERT_USER_LOGIN_FAILURE_LEVEL("smp.alert.user.login_failure.level",
+            "LOW", "Alert level for login failure.", false, false,false, STRING),
+    ALERT_USER_LOGIN_FAILURE_MAIL_SUBJECT("smp.alert.user.login_failure.mail.subject",
+            "Login failure", "Login failure mail subject. Values: {LOW, MEDIUM, HIGH}", false, false,false, STRING),
+
+    ALERT_USER_SUSPENDED_ENABLED("smp.alert.user.suspended.enabled",
+            "true", "Enable/disable the login suspended alert of the authentication module.", false, false,false, BOOLEAN),
+    ALERT_USER_SUSPENDED_LEVEL("smp.alert.user.suspended.level",
+            "HIGH", "Alert level for login suspended. Values: {LOW, MEDIUM, HIGH}", false, false,false, STRING),
+    ALERT_USER_SUSPENDED_MAIL_SUBJECT("smp.alert.user.suspended.mail.subject",
+            "Login credentials suspended", "Login suspended mail subject.", false, false,false, STRING),
+    ALERT_USER_SUSPENDED_MOMENT("smp.alert.user.suspended.mail.moment",
+            "WHEN_BLOCKED", "#When should the account disabled alert be triggered. Values: AT_LOGON: An alert will be triggered each time a user tries to login to a disabled account. WHEN_BLOCKED: An alert will be triggered once when the account got suspended.", false, false,false, STRING),
+
     ALERT_PASSWORD_BEFORE_EXPIRATION_ENABLED("smp.alert.password.imminent_expiration.enabled",
             "true", "Enable/disable the imminent password expiration alert", false, false,false, BOOLEAN),
     ALERT_PASSWORD_BEFORE_EXPIRATION_PERIOD("smp.alert.password.imminent_expiration.delay_days",
@@ -124,8 +140,8 @@ public enum SMPPropertyEnum {
     ALERT_PASSWORD_BEFORE_EXPIRATION_INTERVAL("smp.alert.password.imminent_expiration.frequency_days",
             "5", "Interval between alerts.", false, false,false, INTEGER),
     ALERT_PASSWORD_BEFORE_EXPIRATION_LEVEL("smp.alert.password.imminent_expiration.level",
-            "LOW", "Password imminent expiration alert level.", false, false,false, STRING),
-    ALERT_PASSWORD_BEFORE_EXPIRATION_MAIL_SUBJECT("ssmp.alert.password.imminent_expiration.mail.subject",
+            "LOW", "Password imminent expiration alert level. Values: {LOW, MEDIUM, HIGH}", false, false,false, STRING),
+    ALERT_PASSWORD_BEFORE_EXPIRATION_MAIL_SUBJECT("smp.alert.password.imminent_expiration.mail.subject",
             "Password imminent expiration", "Password imminent expiration mail subject.", false, false,false, STRING),
 
     ALERT_PASSWORD_EXPIRED_ENABLED("smp.alert.password.expired.enabled",
@@ -135,7 +151,7 @@ public enum SMPPropertyEnum {
     ALERT_PASSWORD_EXPIRED_INTERVAL("smp.alert.password.expired.frequency_days",
             "5", "Frequency in days between alerts.", false, false,false, INTEGER),
     ALERT_PASSWORD_EXPIRED_LEVEL("smp.alert.password.expired.level",
-            "LOW", "Password expiration alert level.", false, false,false, STRING),
+            "LOW", "Password expiration alert level. Values: {LOW, MEDIUM, HIGH}", false, false,false, STRING),
     ALERT_PASSWORD_EXPIRED_MAIL_SUBJECT("smp.alert.password.expired.mail.subject",
             "Password expired", "Password expiration mail subject.", false, false,false, STRING),
 
@@ -146,8 +162,8 @@ public enum SMPPropertyEnum {
     ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_INTERVAL("smp.alert.accessToken.imminent_expiration.frequency_days",
             "5", "Frequency in days between alerts.", false, false,false, INTEGER),
     ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_LEVEL("smp.alert.accessToken.imminent_expiration.level",
-            "LOW", "AccessToken imminent expiration alert level.", false, false,false, STRING),
-    ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_MAIL_SUBJECT("ssmp.alert.accessToken.imminent_expiration.mail.subject",
+            "LOW", "AccessToken imminent expiration alert level. Values: {LOW, MEDIUM, HIGH}", false, false,false, STRING),
+    ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_MAIL_SUBJECT("smp.alert.accessToken.imminent_expiration.mail.subject",
             "Access token imminent expiration", "accessToken imminent expiration mail subject.", false, false,false, STRING),
 
     ALERT_ACCESS_TOKEN_EXPIRED_ENABLED("smp.alert.accessToken.expired.enabled",
@@ -157,7 +173,7 @@ public enum SMPPropertyEnum {
     ALERT_ACCESS_TOKEN_EXPIRED_INTERVAL("smp.alert.accessToken.expired.frequency_days",
             "5", "Frequency in days between alerts.", false, false,false, INTEGER),
     ALERT_ACCESS_TOKEN_EXPIRED_LEVEL("smp.alert.accessToken.expired.level",
-            "LOW", "Access Token expiration alert level.", false, false,false, STRING),
+            "LOW", "Access Token expiration alert level. Values: {LOW, MEDIUM, HIGH}", false, false,false, STRING),
     ALERT_ACCESS_TOKEN_EXPIRED_MAIL_SUBJECT("smp.alert.accessToken.expired.mail.subject",
             "Access token expired", "Password expiration mail subject.", false, false,false, STRING),
 
@@ -168,8 +184,8 @@ public enum SMPPropertyEnum {
     ALERT_CERTIFICATE_BEFORE_EXPIRATION_INTERVAL("smp.alert.certificate.imminent_expiration.frequency_days",
             "5", "Frequency in days between alerts.", false, false,false, INTEGER),
     ALERT_CERTIFICATE_BEFORE_EXPIRATION_LEVEL("smp.alert.certificate.imminent_expiration.level",
-            "LOW", "certificate imminent expiration alert level.", false, false,false, STRING),
-    ALERT_CERTIFICATE_BEFORE_EXPIRATION_MAIL_SUBJECT("ssmp.alert.certificate.imminent_expiration.mail.subject",
+            "LOW", "certificate imminent expiration alert level. Values: {LOW, MEDIUM, HIGH}", false, false,false, STRING),
+    ALERT_CERTIFICATE_BEFORE_EXPIRATION_MAIL_SUBJECT("smp.alert.certificate.imminent_expiration.mail.subject",
             "Certificate imminent expiration", "Certificate imminent expiration mail subject.", false, false,false, STRING),
 
     ALERT_CERTIFICATE_EXPIRED_ENABLED("smp.alert.certificate.expired.enabled",
@@ -179,7 +195,7 @@ public enum SMPPropertyEnum {
     ALERT_CERTIFICATE_EXPIRED_INTERVAL("smp.alert.certificate.expired.frequency_days",
             "5", "Frequency in days between alerts.", false, false,false, INTEGER),
     ALERT_CERTIFICATE_EXPIRED_LEVEL("smp.alert.certificate.expired.level",
-            "LOW", "Certificate expiration alert level.", false, false,false, STRING),
+            "LOW", "Certificate expiration alert level. Values: {LOW, MEDIUM, HIGH}", false, false,false, STRING),
     ALERT_CERTIFICATE_EXPIRED_MAIL_SUBJECT("smp.alert.certificate.expired.mail.subject",
             "Certificate expired", "Password expiration mail subject.", false, false,false, STRING),
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/AlertService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/AlertService.java
index b47dd3bad..b16650985 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/AlertService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/AlertService.java
@@ -11,6 +11,7 @@ import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.mail.MailService;
 import eu.europa.ec.edelivery.smp.services.mail.PropertiesMailModel;
 import eu.europa.ec.edelivery.smp.services.mail.prop.CredentialSuspendedProperties;
+import eu.europa.ec.edelivery.smp.services.mail.prop.CredentialVerificationFailedProperties;
 import eu.europa.ec.edelivery.smp.services.mail.prop.CredentialsExpirationProperties;
 import eu.europa.ec.edelivery.smp.utils.HttpUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -51,7 +52,7 @@ public class AlertService {
         // alert specific properties
         String mailSubject = configurationService.getAlertBeforeExpirePasswordMailSubject();
         AlertLevelEnum alertLevel = configurationService.getAlertBeforeExpirePasswordLevel();
-        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIALS_IMMINENT_EXPIRATION;
+        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_IMMINENT_EXPIRATION;
 
         alertCredentialExpiration(mailSubject, mailTo,
                 credentialType, credentialId, expiredOn,
@@ -70,7 +71,7 @@ public class AlertService {
         // alert specific properties
         String mailSubject = configurationService.getAlertExpiredPasswordMailSubject();
         AlertLevelEnum alertLevel = configurationService.getAlertExpiredPasswordLevel();
-        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIALS_EXPIRED;
+        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_EXPIRED;
 
         alertCredentialExpiration(mailSubject, mailTo,
                 credentialType, credentialId, expiredOn,
@@ -91,7 +92,7 @@ public class AlertService {
         // alert specific properties
         String mailSubject = configurationService.getAlertBeforeExpireAccessTokenMailSubject();
         AlertLevelEnum alertLevel = configurationService.getAlertBeforeExpireAccessTokenLevel();
-        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIALS_IMMINENT_EXPIRATION;
+        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_IMMINENT_EXPIRATION;
 
         alertCredentialExpiration(mailSubject, mailTo,
                 credentialType, credentialId, expiredOn,
@@ -112,7 +113,7 @@ public class AlertService {
         // alert specific properties
         String mailSubject = configurationService.getAlertExpiredAccessTokenMailSubject();
         AlertLevelEnum alertLevel = configurationService.getAlertExpiredAccessTokenLevel();
-        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIALS_EXPIRED;
+        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_EXPIRED;
 
         alertCredentialExpiration(mailSubject, mailTo,
                 credentialType, credentialId, expiredOn,
@@ -134,7 +135,7 @@ public class AlertService {
         // alert specific properties
         String mailSubject = configurationService.getAlertBeforeExpireCertificateMailSubject();
         AlertLevelEnum alertLevel = configurationService.getAlertBeforeExpireCertificateLevel();
-        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIALS_IMMINENT_EXPIRATION;
+        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_IMMINENT_EXPIRATION;
 
         alertCredentialExpiration(mailSubject, mailTo,
                 credentialType, credentialId, expiredOn,
@@ -155,7 +156,7 @@ public class AlertService {
         // alert specific properties
         String mailSubject = configurationService.getAlertExpiredCertificateMailSubject();
         AlertLevelEnum alertLevel = configurationService.getAlertExpiredCertificateLevel();
-        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIALS_EXPIRED;
+        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_EXPIRED;
 
         alertCredentialExpiration(mailSubject, mailTo,
                 credentialType, credentialId, expiredOn,
@@ -209,33 +210,42 @@ public class AlertService {
         alertDao.update(alert);
     }
 
-    public void alertUsernamePasswordCredentialsSuspended(DBUser user) {
+    public void alertCredentialVerificationFailed(DBUser user,CredentialTypeEnum credentialType) {
+        Boolean loginFailureEnabled = configurationService.getAlertUserLoginFailureEnabled();
+        if (!loginFailureEnabled) {
+            LOG.debug("Alert Login failure is disabled!" );
+            return;
+        }
+
         String mailTo = user.getEmailAddress();
-        String mailSubject = "User account is suspended";
-        AlertLevelEnum level = AlertLevelEnum.LOW;
-        AlertTypeEnum alertType = AlertTypeEnum.ACCOUNT_SUSPENDED;
+        String mailSubject = configurationService.getAlertBeforeUserSuspendedSubject();
+        AlertLevelEnum level = configurationService.getAlertUserSuspendedLevel();
+        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_VERIFICATION_FAILED;
         Integer failureCount = user.getSequentialLoginFailureCount();
         OffsetDateTime lastFailedLoginDate = user.getLastFailedLoginAttempt();
-        OffsetDateTime suspendedUtil = lastFailedLoginDate.plusSeconds(configurationService.getLoginSuspensionTimeInSeconds());
-        CredentialTypeEnum credentialType = CredentialTypeEnum.USERNAME_PASSWORD;
         String credentialId = user.getUsername();
 
-        alertCredentialSuspended(mailSubject, mailTo,
+        alertCredentialVerificationFailed(mailSubject, mailTo,
                 credentialType, credentialId,
-                failureCount, lastFailedLoginDate, suspendedUtil,
+                failureCount, lastFailedLoginDate,
                 level, alertType);
     }
 
-    public void alertAccessTokenCredentialsSuspended(DBUser user) {
+    public void alertCredentialsSuspended(DBUser user, CredentialTypeEnum credentialType) {
+        Boolean suspensionAlertEnabled = configurationService.getAlertUserSuspendedEnabled();
+        if (!suspensionAlertEnabled) {
+            LOG.debug("Alert suspended is disabled!" );
+            return;
+        }
+
         String mailTo = user.getEmailAddress();
-        String mailSubject = "User access token is suspended";
-        AlertLevelEnum level = AlertLevelEnum.LOW;
-        AlertTypeEnum alertType = AlertTypeEnum.ACCOUNT_SUSPENDED;
-        Integer failureCount = user.getSequentialTokenLoginFailureCount();
-        OffsetDateTime lastFailedLoginDate = user.getLastTokenFailedLoginAttempt();
-        OffsetDateTime suspendedUtil = lastFailedLoginDate.plusSeconds(configurationService.getAccessTokenLoginSuspensionTimeInSeconds());
-        CredentialTypeEnum credentialType = CredentialTypeEnum.ACCESS_TOKEN;
-        String credentialId = user.getAccessTokenIdentifier();
+        String mailSubject = configurationService.getAlertBeforeUserSuspendedSubject();
+        AlertLevelEnum level = configurationService.getAlertUserSuspendedLevel();
+        AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_SUSPENDED;
+        Integer failureCount = user.getSequentialLoginFailureCount();
+        OffsetDateTime lastFailedLoginDate = user.getLastFailedLoginAttempt();
+        OffsetDateTime suspendedUtil = lastFailedLoginDate.plusSeconds(configurationService.getLoginSuspensionTimeInSeconds());
+        String credentialId = user.getUsername();
 
         alertCredentialSuspended(mailSubject, mailTo,
                 credentialType, credentialId,
@@ -243,7 +253,42 @@ public class AlertService {
                 level, alertType);
     }
 
+    public void alertCredentialVerificationFailed(String mailSubject,
+                                         String mailTo,
+                                         CredentialTypeEnum credentialType,
+                                         String credentialId,
+                                         Integer failedLoginCount,
+                                         OffsetDateTime lastFailedLoginDate,
+                                         AlertLevelEnum level,
+                                         AlertTypeEnum alertType) {
+
+        Boolean suspensionAlertEnabled = configurationService.getAlertUserLoginFailureEnabled();
+        if (!suspensionAlertEnabled) {
+            LOG.debug("Alert suspended is disabled!" );
+            return;
+        }
 
+        OffsetDateTime reportDate = OffsetDateTime.now();
+        String serverName = HttpUtils.getServerAddress();
+
+        DBAlert alert = new DBAlert();
+        alert.setProcessed(false);
+        alert.setMailSubject(mailSubject);
+        alert.setMailTo(mailTo);
+        alert.setReportingTime(reportDate);
+        alert.setAlertType(alertType);
+        alert.setAlertLevel(level);
+        alert.addProperty(CredentialVerificationFailedProperties.CREDENTIAL_TYPE.name(), credentialType.name());
+        alert.addProperty(CredentialVerificationFailedProperties.CREDENTIAL_ID.name(), credentialId);
+        alert.addProperty(CredentialVerificationFailedProperties.FAILED_LOGIN_ATTEMPT.name(), failedLoginCount.toString());
+        alert.addProperty(CredentialVerificationFailedProperties.LAST_LOGIN_FAILURE_DATETIME.name(), lastFailedLoginDate);
+        alert.addProperty(CredentialVerificationFailedProperties.REPORTING_DATETIME.name(), reportDate);
+        alert.addProperty(CredentialVerificationFailedProperties.ALERT_LEVEL.name(), level.name());
+        alert.addProperty(CredentialVerificationFailedProperties.SERVER_NAME.name(), serverName);
+        alertDao.persistFlushDetach(alert);
+        // submit alerts
+        submitAlertMail(alert);
+    }
     public void alertCredentialSuspended(String mailSubject,
                                          String mailTo,
                                          CredentialTypeEnum credentialType,
@@ -275,7 +320,6 @@ public class AlertService {
         alertDao.persistFlushDetach(alert);
         // submit alerts
         submitAlertMail(alert);
-
     }
 
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java
index c98dcba63..c5b25fb48 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java
@@ -2,22 +2,17 @@ package eu.europa.ec.edelivery.smp.services;
 
 import eu.europa.ec.edelivery.smp.auth.enums.SMPUserAuthenticationTypes;
 import eu.europa.ec.edelivery.smp.data.dao.ConfigurationDao;
-import eu.europa.ec.edelivery.smp.data.model.DBConfiguration;
 import eu.europa.ec.edelivery.smp.data.ui.enums.AlertLevelEnum;
+import eu.europa.ec.edelivery.smp.data.ui.enums.AlertSuspensionMomentEnum;
 import eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum;
-import eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyTypeEnum;
-import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
-import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
-import eu.europa.ec.edelivery.smp.utils.PropertyUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 
 import java.io.File;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.regex.Pattern;
 
@@ -44,8 +39,9 @@ public class ConfigurationService {
     }
 
     public String getParticipantIdentifierSchemeRexExpMessage() {
-        return (String)configurationDAO.getCachedPropertyValue(PARTC_SCH_REGEXP_MSG);
+        return (String) configurationDAO.getCachedPropertyValue(PARTC_SCH_REGEXP_MSG);
     }
+
     public Boolean getForceConcatenateEBCorePartyId() {
         Boolean value = (Boolean) configurationDAO.getCachedPropertyValue(PARTC_EBCOREPARTYID_CONCATENATE);
         // true by default
@@ -55,6 +51,7 @@ public class ConfigurationService {
     public Pattern getPasswordPolicyRexExp() {
         return (Pattern) configurationDAO.getCachedPropertyValue(PASSWORD_POLICY_REGULAR_EXPRESSION);
     }
+
     public String getPasswordPolicyRexExpPattern() {
         return configurationDAO.getCachedProperty(PASSWORD_POLICY_REGULAR_EXPRESSION);
     }
@@ -66,9 +63,11 @@ public class ConfigurationService {
     public Integer getPasswordPolicyValidDays() {
         return (Integer) configurationDAO.getCachedPropertyValue(PASSWORD_POLICY_VALID_DAYS);
     }
+
     public Integer getPasswordPolicyUIWarningDaysBeforeExpire() {
         return (Integer) configurationDAO.getCachedPropertyValue(PASSWORD_POLICY_UIWARNING_DAYS_BEFORE_EXPIRE);
     }
+
     public Boolean getPasswordPolicyForceChangeIfExpired() {
         return (Boolean) configurationDAO.getCachedPropertyValue(PASSWORD_POLICY_FORCE_CHANGE_EXPIRED);
     }
@@ -80,6 +79,7 @@ public class ConfigurationService {
     public Integer getLoginMaxAttempts() {
         return (Integer) configurationDAO.getCachedPropertyValue(USER_MAX_FAILED_ATTEMPTS);
     }
+
     public Integer getLoginSuspensionTimeInSeconds() {
         return (Integer) configurationDAO.getCachedPropertyValue(USER_SUSPENSION_TIME);
     }
@@ -87,6 +87,7 @@ public class ConfigurationService {
     public Integer getAccessTokenLoginMaxAttempts() {
         return (Integer) configurationDAO.getCachedPropertyValue(ACCESS_TOKEN_MAX_FAILED_ATTEMPTS);
     }
+
     public Integer getAccessTokenLoginSuspensionTimeInSeconds() {
         return (Integer) configurationDAO.getCachedPropertyValue(ACCESS_TOKEN_SUSPENSION_TIME);
     }
@@ -208,7 +209,7 @@ public class ConfigurationService {
     }
 
     public Pattern getSMLIntegrationServerCertSubjectRegExp() {
-        return (Pattern)configurationDAO.getCachedPropertyValue(SML_TLS_SERVER_CERT_SUBJECT_REGEXP);
+        return (Pattern) configurationDAO.getCachedPropertyValue(SML_TLS_SERVER_CERT_SUBJECT_REGEXP);
     }
 
 
@@ -304,17 +305,55 @@ public class ConfigurationService {
         return (List<String>) configurationDAO.getCachedPropertyValue(AUTOMATION_AUTHENTICATION_TYPES);
     }
 
+    //-----------------------
+    // before user suspended
+    public Boolean getAlertUserLoginFailureEnabled() {
+        return (Boolean) configurationDAO.getCachedPropertyValue(ALERT_USER_LOGIN_FAILURE_ENABLED);
+    }
+
+    public AlertLevelEnum getAlertUserLoginFailureLevel() {
+        String level = (String) configurationDAO.getCachedPropertyValue(ALERT_USER_LOGIN_FAILURE_LEVEL);
+        return AlertLevelEnum.valueOf(level);
+    }
+
+    public String getAlertBeforeUserLoginFailureSubject() {
+        return (String) configurationDAO.getCachedPropertyValue(ALERT_USER_LOGIN_FAILURE_MAIL_SUBJECT);
+    }
+
+    //-----------------------
+    // user suspended
+    public Boolean getAlertUserSuspendedEnabled() {
+        return (Boolean) configurationDAO.getCachedPropertyValue(ALERT_USER_SUSPENDED_ENABLED);
+    }
+
+    public AlertLevelEnum getAlertUserSuspendedLevel() {
+        String level = (String) configurationDAO.getCachedPropertyValue(ALERT_USER_SUSPENDED_LEVEL);
+        return AlertLevelEnum.valueOf(level);
+    }
+
+    public String getAlertBeforeUserSuspendedSubject() {
+        return (String) configurationDAO.getCachedPropertyValue(ALERT_USER_SUSPENDED_MAIL_SUBJECT);
+    }
+
+    public AlertSuspensionMomentEnum getAlertBeforeUserSuspendedAlertMoment() {
+        String moment = (String) configurationDAO.getCachedPropertyValue(ALERT_USER_SUSPENDED_MOMENT);
+        return AlertSuspensionMomentEnum.valueOf(moment);
+    }
+
     //-----------------------
     // before password expire
     public Boolean getAlertBeforeExpirePasswordEnabled() {
         return (Boolean) configurationDAO.getCachedPropertyValue(ALERT_PASSWORD_BEFORE_EXPIRATION_ENABLED);
     }
+
     public Integer getAlertBeforeExpirePasswordPeriod() {
         return (Integer) configurationDAO.getCachedPropertyValue(ALERT_PASSWORD_BEFORE_EXPIRATION_PERIOD);
     }
+
     public Integer getAlertBeforeExpirePasswordInterval() {
         return (Integer) configurationDAO.getCachedPropertyValue(ALERT_PASSWORD_BEFORE_EXPIRATION_INTERVAL);
     }
+
     public AlertLevelEnum getAlertBeforeExpirePasswordLevel() {
         String level = (String) configurationDAO.getCachedPropertyValue(ALERT_PASSWORD_BEFORE_EXPIRATION_LEVEL);
         return AlertLevelEnum.valueOf(level);
@@ -328,12 +367,15 @@ public class ConfigurationService {
     public Boolean getAlertExpiredPasswordEnabled() {
         return (Boolean) configurationDAO.getCachedPropertyValue(ALERT_PASSWORD_EXPIRED_ENABLED);
     }
+
     public Integer getAlertExpiredPasswordPeriod() {
         return (Integer) configurationDAO.getCachedPropertyValue(ALERT_PASSWORD_EXPIRED_PERIOD);
     }
+
     public Integer getAlertExpiredPasswordInterval() {
         return (Integer) configurationDAO.getCachedPropertyValue(ALERT_PASSWORD_EXPIRED_INTERVAL);
     }
+
     public AlertLevelEnum getAlertExpiredPasswordLevel() {
         String level = (String) configurationDAO.getCachedPropertyValue(ALERT_PASSWORD_EXPIRED_LEVEL);
         return AlertLevelEnum.valueOf(level);
@@ -348,33 +390,42 @@ public class ConfigurationService {
     public Boolean getAlertBeforeExpireAccessTokenEnabled() {
         return (Boolean) configurationDAO.getCachedPropertyValue(ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_ENABLED);
     }
+
     public Integer getAlertBeforeExpireAccessTokenPeriod() {
         return (Integer) configurationDAO.getCachedPropertyValue(ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_PERIOD);
     }
+
     public Integer getAlertBeforeExpireAccessTokenInterval() {
         return (Integer) configurationDAO.getCachedPropertyValue(ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_INTERVAL);
     }
+
     public AlertLevelEnum getAlertBeforeExpireAccessTokenLevel() {
         String level = (String) configurationDAO.getCachedPropertyValue(ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_LEVEL);
         return AlertLevelEnum.valueOf(level);
     }
+
     public String getAlertBeforeExpireAccessTokenMailSubject() {
         return (String) configurationDAO.getCachedPropertyValue(ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_MAIL_SUBJECT);
     }
+
     // expired access token alerts
     public Boolean getAlertExpiredAccessTokenEnabled() {
         return (Boolean) configurationDAO.getCachedPropertyValue(ALERT_ACCESS_TOKEN_EXPIRED_ENABLED);
     }
+
     public Integer getAlertExpiredAccessTokenPeriod() {
         return (Integer) configurationDAO.getCachedPropertyValue(ALERT_ACCESS_TOKEN_EXPIRED_PERIOD);
     }
+
     public Integer getAlertExpiredAccessTokenInterval() {
         return (Integer) configurationDAO.getCachedPropertyValue(ALERT_ACCESS_TOKEN_EXPIRED_INTERVAL);
     }
+
     public AlertLevelEnum getAlertExpiredAccessTokenLevel() {
         String level = (String) configurationDAO.getCachedPropertyValue(ALERT_ACCESS_TOKEN_EXPIRED_LEVEL);
         return AlertLevelEnum.valueOf(level);
     }
+
     public String getAlertExpiredAccessTokenMailSubject() {
         return (String) configurationDAO.getCachedPropertyValue(ALERT_ACCESS_TOKEN_EXPIRED_MAIL_SUBJECT);
     }
@@ -384,33 +435,42 @@ public class ConfigurationService {
     public Boolean getAlertBeforeExpireCertificateEnabled() {
         return (Boolean) configurationDAO.getCachedPropertyValue(ALERT_CERTIFICATE_BEFORE_EXPIRATION_ENABLED);
     }
+
     public Integer getAlertBeforeExpireCertificatePeriod() {
         return (Integer) configurationDAO.getCachedPropertyValue(ALERT_CERTIFICATE_BEFORE_EXPIRATION_PERIOD);
     }
+
     public Integer getAlertBeforeExpireCertificateInterval() {
         return (Integer) configurationDAO.getCachedPropertyValue(ALERT_CERTIFICATE_BEFORE_EXPIRATION_INTERVAL);
     }
+
     public AlertLevelEnum getAlertBeforeExpireCertificateLevel() {
         String level = (String) configurationDAO.getCachedPropertyValue(ALERT_CERTIFICATE_BEFORE_EXPIRATION_LEVEL);
         return AlertLevelEnum.valueOf(level);
     }
+
     public String getAlertBeforeExpireCertificateMailSubject() {
         return (String) configurationDAO.getCachedPropertyValue(ALERT_CERTIFICATE_BEFORE_EXPIRATION_MAIL_SUBJECT);
     }
+
     // expired access token alerts
     public Boolean getAlertExpiredCertificateEnabled() {
         return (Boolean) configurationDAO.getCachedPropertyValue(ALERT_CERTIFICATE_EXPIRED_ENABLED);
     }
+
     public Integer getAlertExpiredCertificatePeriod() {
         return (Integer) configurationDAO.getCachedPropertyValue(ALERT_CERTIFICATE_EXPIRED_PERIOD);
     }
+
     public Integer getAlertExpiredCertificateInterval() {
         return (Integer) configurationDAO.getCachedPropertyValue(ALERT_CERTIFICATE_EXPIRED_INTERVAL);
     }
+
     public AlertLevelEnum getAlertExpiredCertificateLevel() {
         String level = (String) configurationDAO.getCachedPropertyValue(ALERT_CERTIFICATE_EXPIRED_LEVEL);
         return AlertLevelEnum.valueOf(level);
     }
+
     public String getAlertExpiredCertificateMailSubject() {
         return (String) configurationDAO.getCachedPropertyValue(ALERT_CERTIFICATE_EXPIRED_MAIL_SUBJECT);
     }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/mail/prop/CredentialVerificationFailedProperties.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/mail/prop/CredentialVerificationFailedProperties.java
new file mode 100644
index 000000000..8c69cb395
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/mail/prop/CredentialVerificationFailedProperties.java
@@ -0,0 +1,11 @@
+package eu.europa.ec.edelivery.smp.services.mail.prop;
+
+public enum CredentialVerificationFailedProperties {
+    CREDENTIAL_TYPE,
+    CREDENTIAL_ID,
+    FAILED_LOGIN_ATTEMPT,
+    LAST_LOGIN_FAILURE_DATETIME,
+    REPORTING_DATETIME,
+    ALERT_LEVEL,
+    SERVER_NAME,
+}
diff --git a/smp-server-library/src/main/resources/alert-mail-templates/credentials_expired.ftl b/smp-server-library/src/main/resources/alert-mail-templates/credential_expired.ftl
similarity index 100%
rename from smp-server-library/src/main/resources/alert-mail-templates/credentials_expired.ftl
rename to smp-server-library/src/main/resources/alert-mail-templates/credential_expired.ftl
diff --git a/smp-server-library/src/main/resources/alert-mail-templates/credentials_imminent_expiration.ftl b/smp-server-library/src/main/resources/alert-mail-templates/credential_imminent_expiration.ftl
similarity index 100%
rename from smp-server-library/src/main/resources/alert-mail-templates/credentials_imminent_expiration.ftl
rename to smp-server-library/src/main/resources/alert-mail-templates/credential_imminent_expiration.ftl
diff --git a/smp-server-library/src/main/resources/alert-mail-templates/account_suspended.ftl b/smp-server-library/src/main/resources/alert-mail-templates/credential_suspended.ftl
similarity index 98%
rename from smp-server-library/src/main/resources/alert-mail-templates/account_suspended.ftl
rename to smp-server-library/src/main/resources/alert-mail-templates/credential_suspended.ftl
index 49df1e8bc..53c653cf1 100644
--- a/smp-server-library/src/main/resources/alert-mail-templates/account_suspended.ftl
+++ b/smp-server-library/src/main/resources/alert-mail-templates/credential_suspended.ftl
@@ -59,7 +59,7 @@
                             <!-- TITLE -->
                             <tr>
                               <td valign="top" align="left" style=" font-size: 20px; font-family: Arial, Helvetica, sans-serif; color: #000;"><br/>
-                                Account is temporarly susspended</td>
+                                Account is suspended</td>
                             </tr>
                             <!-- / TITLE --> 
                             
diff --git a/smp-server-library/src/main/resources/alert-mail-templates/credential_verification_failed.ftl b/smp-server-library/src/main/resources/alert-mail-templates/credential_verification_failed.ftl
new file mode 100644
index 000000000..9f3de0870
--- /dev/null
+++ b/smp-server-library/src/main/resources/alert-mail-templates/credential_verification_failed.ftl
@@ -0,0 +1,117 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>eDelivery SMP</title>
+</head>
+<body style="margin:0; padding:0; background-color: #f1f1f1;">
+<center>
+  <table width="100%" border="0" cellspacing="0" cellpadding="0" style="background-color: #f1f1f1;">
+    <tr>
+      <td><!-- MARGIN TOP -->
+        
+        <table width="100%" border="0" cellspacing="0" cellpadding="0" style="background-color: #f1f1f1;">
+          <tr>
+            <td>&nbsp;</td>
+          </tr>
+        </table>
+        
+        <!-- / MARGIN TOP -->
+        
+        <table width="540" align="center" border="0" cellspacing="0" cellpadding="0">
+          <tr> 
+            <!-- MARGIN LEFT -->
+            <td width="20" valign="top">&nbsp;</td>
+            <!-- / MARGIN LEFT -->
+            <td width="500" valign="top"><!-- WRAPPER -->
+              
+              <table width="500" border="0" cellpadding="0" cellspacing="0">
+                <tr>
+                  <td valign="top" style="border:5px solid #4cbdce;"><table width="100%" border="0" cellspacing="0" cellpadding="0" style="background-color: #ffffff;">
+                      <tr> 
+                        <!-- COL LEFT -->
+                        <td width="20" valign="top">&nbsp;</td>
+                        <!-- / COL LEFT --> 
+                        
+                        <!-- CENTER -->
+                        <td width="460" valign="top"><table width="100%" border="0" cellspacing="0" cellpadding="0">
+                            <tr>
+                              <td height="20" valign="top">&nbsp;</td>
+                            </tr>
+                            
+                            <!-- TITLE -->
+                            <tr>
+                              <td valign="top" align="left" style=" font-size: 30px; font-family: Arial, Helvetica, sans-serif; color: #000;">eDelivery SMP<br/></td>
+                            </tr>
+                            <!-- / TITLE --> 
+                            
+                            <!-- UNDERLINE -->
+                            <tr>
+                              <td valign="top"><table width="100%" border="0" cellspacing="0" cellpadding="0">
+                                  <tr>
+                                    <td width="60" height="10" style="border-bottom:3px solid #4cbdce"></td>
+                                    <td width="400" height="5"></td>
+                                  </tr>
+                                </table></td>
+                            </tr>
+                            <!-- / UNDERLINE --> 
+                            
+                            <!-- TITLE -->
+                            <tr>
+                              <td valign="top" align="left" style=" font-size: 20px; font-family: Arial, Helvetica, sans-serif; color: #000;"><br/>
+                                Account is temporarly suspended</td>
+                            </tr>
+                            <!-- / TITLE --> 
+                            
+                            <!-- UNDERLINE -->
+                            <tr>
+                              <td valign="top"><table width="100%" border="0" cellspacing="0" cellpadding="0">
+                                  <tr>
+                                    <td width="30" height="10" style="border-bottom:3px solid #000000"></td>
+                                    <td width="430" height="5"></td>
+                                  </tr>
+                                </table></td>
+                            </tr>
+                            <!-- / UNDERLINE --> 
+                            
+                            <!-- MAIN CONTENT -->
+                            <tr>
+                              <td valign="top" align="left" style=" font-size: 13px; font-family: Arial, Helvetica, sans-serif; color: #000;"><br/>
+                                <br/>
+                                  <p><strong>Credential type:</strong> ${CREDENTIAL_TYPE}</p>
+                                  <p><strong>Credential id:</strong> ${CREDENTIAL_ID}</p>
+                                  <p><strong>Failed login attempt count:</strong> ${FAILED_LOGIN_ATTEMPT}</p>
+                                  <p><strong>Last failed login time:</strong> ${LAST_LOGIN_FAILURE_DATETIME}</p>
+                                  <p><strong>Reporting time:</strong> ${REPORTING_TIME}</p>
+                                  <p><strong>Alert level:</strong> ${ALERT_LEVEL}</p>
+                                  <p><strong>Server name:</strong> ${SERVER_NAME}</p>
+                                </td>
+                            </tr>
+                            <!-- / MAIN CONTENT -->
+                            
+                            <tr>
+                              <td height="20" valign="top">&nbsp;</td>
+                            </tr>
+                          </table></td>
+                        <!-- / CENTER --> 
+                        <!-- COL RIGHT -->
+                        <td width="20" valign="top">&nbsp;</td>
+                        <!-- / COL RIGHT --> 
+                      </tr>
+                    </table></td>
+                </tr>
+              </table>
+              
+              <!-- / WRAPPER --></td>
+            <!-- MARGIN RIGHT -->
+            <td width="20" valign="top"></td>
+            <!-- / MARGIN RIGHT --> 
+          </tr>
+        </table>
+        
+       </td>
+    </tr>
+  </table>
+</center>
+</body>
+</html>
\ No newline at end of file
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/AuditIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/AuditIntegrationTest.java
index 16aa479d1..fdc3414a4 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/AuditIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/AuditIntegrationTest.java
@@ -88,7 +88,7 @@ public class AuditIntegrationTest {
         DBAlert dbAlert = createDBAlert();
         Map<String, Object> alterVal = new HashMap<>();
         alterVal.put("processed", false);
-        alterVal.put("alertType", AlertTypeEnum.CREDENTIALS_IMMINENT_EXPIRATION);
+        alterVal.put("alertType", AlertTypeEnum.CREDENTIAL_IMMINENT_EXPIRATION);
         alterVal.put("alertStatus", AlertStatusEnum.FAILED);
         testAuditEntity(dbAlert, alterVal);
     }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java
index 8e570b0ad..4e0bbf18f 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java
@@ -25,7 +25,6 @@ public class TestDBUtils {
         return domain;
     }
 
-
     public static DBDomain createDBDomain() {
         return createDBDomain(TestConstants.TEST_DOMAIN_CODE_1);
     }
@@ -85,7 +84,7 @@ public class TestDBUtils {
         DBAlert dbalert = new DBAlert();
         dbalert.setAlertLevel(AlertLevelEnum.MEDIUM);
         dbalert.setAlertStatus(AlertStatusEnum.SUCCESS);
-        dbalert.setAlertType(AlertTypeEnum.CREDENTIALS_IMMINENT_EXPIRATION);
+        dbalert.setAlertType(AlertTypeEnum.CREDENTIAL_IMMINENT_EXPIRATION);
         dbalert.setProcessed(true);
         dbalert.setProcessedTime(OffsetDateTime.now());
         dbalert.setReportingTime(OffsetDateTime.now());
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java
index 7a3361afb..308882b26 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java
@@ -6,6 +6,8 @@ import eu.europa.ec.edelivery.smp.data.dao.UserDao;
 import eu.europa.ec.edelivery.smp.data.model.DBCertificate;
 import eu.europa.ec.edelivery.smp.data.model.DBUser;
 import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
+import eu.europa.ec.edelivery.smp.data.ui.enums.AlertSuspensionMomentEnum;
+import eu.europa.ec.edelivery.smp.data.ui.enums.CredentialTypeEnum;
 import eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
@@ -244,6 +246,9 @@ public class SMPAuthenticationProvider implements AuthenticationProvider {
             LOG.warn("User [{}] failed login attempt [{}]! did not reach the max failed attempts [{}]", user.getUsername(), user.getSequentialTokenLoginFailureCount(), configurationService.getAccessTokenLoginMaxAttempts());
             return;
         }
+        if (configurationService.getAlertBeforeUserSuspendedAlertMoment() == AlertSuspensionMomentEnum.AT_LOGON) {
+            alertService.alertCredentialsSuspended(user, CredentialTypeEnum.ACCESS_TOKEN);
+        }
         LOG.securityWarn(SMPMessageCode.SEC_USER_SUSPENDED, user.getUsername());
         throw new BadCredentialsException("The user is suspended. Please try again later or contact your administrator.");
     }
@@ -311,7 +316,9 @@ public class SMPAuthenticationProvider implements AuthenticationProvider {
         LOG.securityWarn(SMPMessageCode.SEC_INVALID_PASSWORD, user.getUsername());
         if (user.getSequentialTokenLoginFailureCount() >= configurationService.getAccessTokenLoginMaxAttempts()) {
             LOG.info("User access token [{}] failed sequential attempt exceeded the max allowed attempts [{}]!", user.getAccessToken(), configurationService.getAccessTokenLoginMaxAttempts());
-            alertService.alertAccessTokenCredentialsSuspended(user);
+            alertService.alertCredentialsSuspended(user, CredentialTypeEnum.ACCESS_TOKEN);
+        } else {
+            alertService.alertCredentialVerificationFailed(user, CredentialTypeEnum.ACCESS_TOKEN);
         }
         throw new BadCredentialsException(LOGIN_FAILED_MESSAGE);
     }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProviderForUI.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProviderForUI.java
index a140c7af6..d3de04a62 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProviderForUI.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProviderForUI.java
@@ -3,6 +3,8 @@ package eu.europa.ec.edelivery.smp.auth;
 import eu.europa.ec.edelivery.smp.data.dao.UserDao;
 import eu.europa.ec.edelivery.smp.data.model.DBUser;
 import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
+import eu.europa.ec.edelivery.smp.data.ui.enums.AlertSuspensionMomentEnum;
+import eu.europa.ec.edelivery.smp.data.ui.enums.CredentialTypeEnum;
 import eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
@@ -83,7 +85,6 @@ public class SMPAuthenticationProviderForUI implements AuthenticationProvider {
                 LOG.debug("User with username does not exists [{}], continue with next authentication provider");
                 return null;
             }
-
             user = oUsr.get();
         } catch (AuthenticationException ex) {
             LOG.securityWarn(SMPMessageCode.SEC_USER_NOT_AUTHENTICATED, username, ExceptionUtils.getRootCause(ex), ex);
@@ -122,7 +123,9 @@ public class SMPAuthenticationProviderForUI implements AuthenticationProvider {
         LOG.securityWarn(SMPMessageCode.SEC_INVALID_PASSWORD, user.getUsername());
         if (user.getSequentialLoginFailureCount() >= configurationService.getLoginMaxAttempts()) {
             LOG.info("User [{}] failed sequential attempt exceeded the max allowed attempts [{}]!", user.getUsername(), configurationService.getLoginMaxAttempts());
-            alertService.alertUsernamePasswordCredentialsSuspended(user);
+            alertService.alertCredentialsSuspended(user, CredentialTypeEnum.USERNAME_PASSWORD);
+        } else {
+            alertService.alertCredentialVerificationFailed(user, CredentialTypeEnum.USERNAME_PASSWORD);
         }
         throw new BadCredentialsException("Login failed; Invalid userID or password");
     }
@@ -162,6 +165,9 @@ public class SMPAuthenticationProviderForUI implements AuthenticationProvider {
             LOG.warn("User [{}] failed login attempt [{}]! did not reach the max failed attempts [{}]", user.getUsername(), user.getSequentialLoginFailureCount(), configurationService.getLoginMaxAttempts());
             return;
         }
+        if (configurationService.getAlertBeforeUserSuspendedAlertMoment() == AlertSuspensionMomentEnum.AT_LOGON) {
+            alertService.alertCredentialsSuspended(user, CredentialTypeEnum.USERNAME_PASSWORD);
+        }
         LOG.securityWarn(SMPMessageCode.SEC_USER_SUSPENDED, user.getUsername());
         throw new BadCredentialsException("The user is suspended. Please try again later or contact your administrator.");
     }
-- 
GitLab