diff --git a/config/install/login_security.settings.yml b/config/install/login_security.settings.yml
index 4dc51fb..ac6277f 100644
--- a/config/install/login_security.settings.yml
+++ b/config/install/login_security.settings.yml
@@ -3,6 +3,7 @@ user_wrong_count: 0
 host_wrong_count: 0
 host_wrong_count_hard: 0
 activity_threshold: 0
+unblock_time: 0
 disable_core_login_error: 0
 notice_attempts_available: 0
 last_login_timestamp: 0
@@ -15,5 +16,6 @@ host_hard_banned: 'The IP address @ip is banned at @site, and will not be able t
 user_blocked: 'The user @username has been blocked due to failed login attempts.'
 user_blocked_email_subject: 'Security action: The user @username has been blocked.'
 user_blocked_email_body: 'The user @username (@edit_uri) has been blocked at @site due to the amount of failed login attempts. Please check the logs for more information.'
+unblock_time_message: 'You are blocked from logging in. You may try again in @unblock_time minutes.'
 login_activity_email_subject: 'Security information: Unexpected login activity has been detected at @site.'
 login_activity_email_body: 'The configured threshold of @activity_threshold logins has been reached with a total of @tracking_current_count invalid login attempts. You should review your log information about login attempts at @site.'
diff --git a/config/schema/login_security.schema.yml b/config/schema/login_security.schema.yml
index 3adbfaf..8a664fd 100644
--- a/config/schema/login_security.schema.yml
+++ b/config/schema/login_security.schema.yml
@@ -17,6 +17,9 @@ login_security.settings:
     activity_threshold:
       type: integer
       label: 'Maximum number of login failures before detecting an ongoing attack'
+    unblock_time:
+      type: integer
+      label: 'Unblock Time'
     disable_core_login_error:
       type: integer
       label: 'Disable login failure error message'
@@ -47,6 +50,9 @@ login_security.settings:
     user_blocked_email_body:
       type: text
       label: 'Email body'
+    unblock_time_message:
+      type: text
+      label: 'User blocked for time period'
     login_activity_email_subject:
       type: label
       label: 'Email subject'
diff --git a/login_security.module b/login_security.module
index a3e289b..d80409d 100644
--- a/login_security.module
+++ b/login_security.module
@@ -62,6 +62,8 @@ function login_security_form_alter(array &$form, FormStateInterface $form_state,
     }
 
     $form['#validate'][] = 'login_security_validate';
+    $form['#validate'][] = '::validateAuthentication';
+    $form['#validate'][] = '::validateFinal';
     $form['#submit'][] = 'login_security_submit';
   }
 }
@@ -184,6 +186,30 @@ function login_security_validate(array $form, FormStateInterface $form_state) {
     }
   }
 
+  $request_time = \Drupal::time()->getRequestTime();
+  $trackTime =   \Drupal::database()->select('login_security_track', 'time')
+    ->fields('time', array('timestamp'))
+    ->condition('name', $name)
+    ->execute()
+    ->fetchField();
+  $unblock_request = $trackTime + ($variables['@unblock_time'] * 60);
+
+  // Check for user login attempts.
+  if ($variables['@user_block_attempts'] >= 1) {
+    if ($variables['@user_current_count'] >= $variables['@user_block_attempts'] && $request_time <= $unblock_request ) {
+      // Block the account.
+      login_user_block_user_name($variables, $form_state);
+
+      $user_blocked = TRUE;
+    }
+    else {
+      // Unblock the account.
+      login_user_unblock_user_name($variables, $form_state);
+
+      $user_blocked = FALSE;
+    }
+  }
+
   // Flood control flag set by Drupal core.
   $flood_control_triggered = $form_state->get('flood_control_triggered');
   // At this point, they're either logged in or not by Drupal core's abuse of
@@ -217,35 +243,42 @@ function login_security_validate(array $form, FormStateInterface $form_state) {
         \Drupal::messenger()->messagesByType('error', TRUE);
       }
 
-      // Should the user be advised about the remaining login attempts?
-      $notice_user = $conf->get('notice_attempts_available');
-      if ($notice_user) {
-        // Notic the user with the message for failed login attempt,
-        // even if the user is blocked.
-        // This will prevent user name enumeration attack.
-        $message_raw = $conf->get('notice_attempts_message');
-
-        // Simple flag that can be changed using hook_alter (see below).
-        $display_block_attempts = TRUE;
-
-        // Allow other module to change the flag, or even the message displayed,
-        // with a custom logic.
-        \Drupal::moduleHandler()->alter('login_security_display_block_attempts', $message_raw, $display_block_attempts, $variables['@user_current_count']);
-
-        $message = [
-          'message' => $message_raw,
-          'variables' => $variables,
-        ];
-
-        // This loop is used instead of doing t() because t() can only
-        // translate static strings, not variables.
-        // Ignoring Coder because $variables is sanitized by
-        // login_security_t().
-        // See https://drupal.org/node/1743996#comment-6421246.
-        // @ignore security_2
-        $message = new FormattableMarkup($message['message'], $message['variables']);
-        if ($display_block_attempts) {
-          \Drupal::messenger()->addWarning($message, TRUE);
+      if ($user_blocked) {
+        // If configured, advise the user they are blocked and may try again in
+        // the configured amount of time.
+        _display_user_blocked_message($name);
+      }
+      else {
+        // Should the user be advised about the remaining login attempts?
+        $notice_user = $conf->get('notice_attempts_available');
+        if ($notice_user) {
+          // Notic the user with the message for failed login attempt,
+          // even if the user is blocked.
+          // This will prevent user name enumeration attack.
+          $message_raw = $conf->get('notice_attempts_message');
+
+          // Simple flag that can be changed using hook_alter (see below).
+          $display_block_attempts = TRUE;
+
+          // Allow other module to change the flag, or even the message displayed,
+          // with a custom logic.
+          \Drupal::moduleHandler()->alter('login_security_display_block_attempts', $message_raw, $display_block_attempts, $variables['@user_current_count']);
+
+          $message = [
+            'message' => $message_raw,
+            'variables' => $variables,
+          ];
+
+          // This loop is used instead of doing t() because t() can only
+          // translate static strings, not variables.
+          // Ignoring Coder because $variables is sanitized by
+          // login_security_t().
+          // See https://drupal.org/node/1743996#comment-6421246.
+          // @ignore security_2
+          $message = new FormattableMarkup($message['message'], $message['variables']);
+          if ($display_block_attempts) {
+            \Drupal::messenger()->addWarning($message, TRUE);
+          }
         }
       }
     }
@@ -258,14 +291,6 @@ function login_security_validate(array $form, FormStateInterface $form_state) {
       login_user_block_ip($variables, $form_state);
     }
   }
-
-  // Check for user login attempts.
-  if ($variables['@user_block_attempts'] >= 1) {
-    if ($variables['@user_current_count'] >= $variables['@user_block_attempts']) {
-      // Block the account $name.
-      login_user_block_user_name($variables, $form_state);
-    }
-  }
 }
 
 /**
@@ -385,6 +410,37 @@ function login_user_block_ip($variables, FormStateInterface $form_state) {
   }
 }
 
+/**
+ * Unlock a user by username
+ */
+function login_user_unblock_user_name($variables, FormStateInterface $form_state) {
+  $conf = \Drupal::config('login_security.settings');
+  // If the user exists.
+  if ($variables['@uid'] > 1) {
+    // Modifying the user table is not an option so it disables the user hooks.
+    // Need to do firing the hook so user_notifications can be used.
+    $uid = $variables['@uid'];
+    $account = User::load($uid);
+    // Block account if is active.
+    if ($account->status->value == 0) {
+      $account->status->setValue(1);
+      $account->save();
+      // The watchdog alert is set to 'user' so it will show with other blocked
+      // user messages.
+      \Drupal::logger('login_security')->notice('Unlocked user @username after the time specified in the Login Security settings.', $variables);
+      $form_errors = $form_state->getErrors();
+      // Clear the form errors.
+      $form_state->clearErrors();
+      // Remove the field_mobile form error.
+      unset($form_errors['name']);
+      // Now loop through and re-apply the remaining form error messages.
+      foreach ($form_errors as $name => $error_message) {
+        $form_state->setErrorByName($name, $error_message);
+      }
+    }
+  }
+}
+
 /**
  * Block a user by user name. If no user id then block current user.
  */
@@ -505,6 +561,7 @@ function _login_security_get_variables_by_name($name = NULL) {
       ->execute()
       ->fetchField(),
     '@activity_threshold' => $config->get('activity_threshold'),
+    '@unblock_time' => $config->get('unblock_time'),
   ];
   return $variables;
 }
@@ -537,3 +594,29 @@ function login_security_help($route_name, RouteMatchInterface $route_match) {
       return '<p>' . t('Make sure you have reviewed the <a href="!README">README file</a> for further information about how all these settings will affect your Drupal login form submissions.', ['!README' => 'http://drupalcode.org/project/login_security.git/blob/refs/heads/6.x-1.x:/README.txt']) . '</p>';
   }
 }
+
+/**
+ * Displays the 'User blocked for time period' message if the user is blocked.
+ *
+ * Note: This function is only used if the 'Unblock Time' value is used.
+ */
+function _display_user_blocked_message($name) {
+  $conf = \Drupal::config('login_security.settings');
+  $variables = _login_security_get_variables_by_name($name);
+  $message_raw = $conf->get('unblock_time_message');
+
+  $message = [
+    'message' => $message_raw,
+    'variables' => $variables,
+  ];
+
+  // This loop is used instead of doing t() because t() can only
+  // translate static strings, not variables.
+  // Ignoring Coder because $variables is sanitized by
+  // login_security_t().
+  // See https://drupal.org/node/1743996#comment-6421246.
+  // @ignore security_2
+  $message = new FormattableMarkup($message['message'], $message['variables']);
+
+  \Drupal::messenger()->addError($message, TRUE);
+}
diff --git a/src/Form/LoginSecurityAdminSettings.php b/src/Form/LoginSecurityAdminSettings.php
index 39515dc..5bdfcdb 100644
--- a/src/Form/LoginSecurityAdminSettings.php
+++ b/src/Form/LoginSecurityAdminSettings.php
@@ -51,6 +51,16 @@ class LoginSecurityAdminSettings extends ConfigFormBase {
         The user blocking protection will not disappear and should be removed manually from the <a href=":user">user management</a> interface.', [':user' => $base_url . '/admin/people']),
       '#field_suffix' => $this->t('failed attempts'),
     ];
+    // Field to get unblock time.
+    $form['general_settings']['unblock_time'] = [
+      '#type' => 'number',
+      '#min' => 0,
+      '#title' => $this->t('Unblock Time'),
+      '#default_value' => $config->get('unblock_time'),
+      '#size' => 3,
+      '#description' => $this->t('User will be unblocked after this time.'),
+      '#field_suffix' => $this->t('minute(s)'),
+    ];
     $form['general_settings']['host_wrong_count'] = [
       '#type' => 'number',
       '#min' => 0,
@@ -182,10 +192,17 @@ class LoginSecurityAdminSettings extends ConfigFormBase {
       '#default_value' => $config->get('user_blocked'),
       '#description' => $this->t('Enter the message to be shown when a user gets blocked due to enough failed login attempts.'),
     ];
+    $form['notification']['message']['unblock_time_message'] = [
+      '#type' => 'textarea',
+      '#rows' => 2,
+      '#title' => $this->t('User blocked for time period'),
+      '#default_value' => $config->get('unblock_time_message'),
+      '#description' => $this->t('Enter the message to be shown when a user is blocked for a specified amount of time via the Unblock Time setting.'),
+    ];
     $form['notification']['tokens'] = [
       '#type' => 'item',
       '#title' => $this->t('Tokens'),
-      '#description' => $this->t("<ul><li>%date: The (formatted) date and time of the event.</li><li>%ip: The IP address tracked for this event.</li><li>%username: The username entered in the login form (sanitized).</li><li>%email: If the user exists, this will be the email address.</li><li>%uid: If the user exists, this will be the user uid.</li><li>%site: The name of the site as configured in the administration.</li><li>%uri: The base url of this Drupal site.</li><li>%edit_uri: Direct link to the user (based on the name entered) edit page.</li><li>%hard_block_attempts: Configured maximum attempts before hard blocking the IP address.</li><li>%soft_block_attempts: Configured maximum attempts before soft blocking the IP address.</li><li>%user_block_attempts: Configured maximum login attempts before blocking the user.</li><li>%user_ip_current_count: The total attempts for this user name tracked from this IP address.</li><li>%ip_current_count: The total login attempts tracked from from this IP address.</li><li>%user_current_count: The total login attempts tracked for this user name .</li><li>%tracking_time: The tracking time value: in hours.</li><li>%tracking_current_count: Total tracked events</li><li>%activity_threshold: Value of attempts to detect ongoing attack.</li></ul>"),
+      '#description' => $this->t("<ul><li>%date: The (formatted) date and time of the event.</li><li>%ip: The IP address tracked for this event.</li><li>%username: The username entered in the login form (sanitized).</li><li>%email: If the user exists, this will be the email address.</li><li>%uid: If the user exists, this will be the user uid.</li><li>%site: The name of the site as configured in the administration.</li><li>%uri: The base url of this Drupal site.</li><li>%edit_uri: Direct link to the user (based on the name entered) edit page.</li><li>%hard_block_attempts: Configured maximum attempts before hard blocking the IP address.</li><li>%soft_block_attempts: Configured maximum attempts before soft blocking the IP address.</li><li>%user_block_attempts: Configured maximum login attempts before blocking the user.</li><li>%user_ip_current_count: The total attempts for this user name tracked from this IP address.</li><li>%ip_current_count: The total login attempts tracked from from this IP address.</li><li>%user_current_count: The total login attempts tracked for this user name .</li><li>%tracking_time: The tracking time value: in hours.</li><li>%tracking_current_count: Total tracked events</li><li>%activity_threshold: Value of attempts to detect ongoing attack.</li><li>%unblock_time: The amount of time the user is blocked.</li></ul>"),
     ];
 
     // Clean event tracking list.
@@ -208,6 +225,7 @@ class LoginSecurityAdminSettings extends ConfigFormBase {
       ->set('host_wrong_count', $form_state->getValue('host_wrong_count'))
       ->set('host_wrong_count_hard', $form_state->getValue('host_wrong_count_hard'))
       ->set('activity_threshold', $form_state->getValue('activity_threshold'))
+      ->set('unblock_time', $form_state->getValue('unblock_time'))
       ->set('disable_core_login_error', $form_state->getValue('disable_core_login_error'))
       ->set('notice_attempts_available', $form_state->getValue('notice_attempts_available'))
       ->set('last_login_timestamp', $form_state->getValue('last_login_timestamp'))
@@ -221,6 +239,7 @@ class LoginSecurityAdminSettings extends ConfigFormBase {
       ->set('user_blocked', $form_state->getValue('user_blocked'))
       ->set('user_blocked_email_subject', $form_state->getValue('user_blocked_email_subject'))
       ->set('user_blocked_email_body', $form_state->getValue('user_blocked_email_body'))
+      ->set('unblock_time_message', $form_state->getValue('unblock_time_message'))
       ->set('login_activity_email_subject', $form_state->getValue('login_activity_email_subject'))
       ->set('login_activity_email_body', $form_state->getValue('login_activity_email_body'))
       ->save();
