diff --git a/config/schema/webform.schema.yml b/config/schema/webform.schema.yml
index 5b946763..35f3dbb0 100644
--- a/config/schema/webform.schema.yml
+++ b/config/schema/webform.schema.yml
@@ -420,7 +420,7 @@ webform.webform.*:
           type: text
           label: 'Preview message'
         draft:
-          type: boolean
+          type: string
           label: 'Allow your users to save and finish the webform later.'
         draft_auto_save:
           type: boolean
diff --git a/src/Entity/Webform.php b/src/Entity/Webform.php
index 343f5574..477a74e3 100644
--- a/src/Entity/Webform.php
+++ b/src/Entity/Webform.php
@@ -541,7 +541,7 @@ class Webform extends ConfigEntityBundleBase implements WebformInterface {
       'preview_prev_button_label' => '',
       'preview_prev_button_attributes' => [],
       'preview_message' => '',
-      'draft' => FALSE,
+      'draft' => self::DRAFT_ENABLED_NONE,
       'draft_auto_save' => FALSE,
       'draft_button_label' => '',
       'draft_button_attributes' => [],
diff --git a/src/WebformEntitySettingsForm.php b/src/WebformEntitySettingsForm.php
index eadac68e..6d1860fc 100644
--- a/src/WebformEntitySettingsForm.php
+++ b/src/WebformEntitySettingsForm.php
@@ -491,17 +491,20 @@ class WebformEntitySettingsForm extends EntityForm {
       ],
     ];
     $form['draft']['draft'] = [
-      '#type' => 'checkbox',
-      '#title' => $this->t('Allow your users to save and finish the webform later.'),
-      "#description" => $this->t('This option is available only for authenticated users.'),
-      '#return_value' => TRUE,
+      '#type' => 'select',
+      '#title' => $this->t('Allow your users to save and finish the webform later'),
       '#default_value' => $settings['draft'],
+      '#options' => [
+        WebformInterface::DRAFT_ENABLED_NONE => $this->t('Disabled'),
+        WebformInterface::DRAFT_ENABLED_AUTHENTICATED => $this->t('Authenticated users'),
+        WebformInterface::DRAFT_ENABLED_ALL => $this->t('Authenticated and anonymous users'),
+      ],
     ];
     $form['draft']['settings'] = [
       '#type' => 'container',
       '#states' => [
-        'visible' => [
-          ':input[name="draft"]' => ['checked' => TRUE],
+        'invisible' => [
+          ':input[name="draft"]' => ['value' => WebformInterface::DRAFT_ENABLED_NONE],
         ],
       ],
     ];
diff --git a/src/WebformInterface.php b/src/WebformInterface.php
index 5378a572..86e90d9a 100644
--- a/src/WebformInterface.php
+++ b/src/WebformInterface.php
@@ -13,6 +13,27 @@ use Drupal\user\EntityOwnerInterface;
 interface WebformInterface extends ConfigEntityInterface, EntityWithPluginCollectionInterface, EntityOwnerInterface {
 
   /**
+   * Denote drafts are not allowed.
+   *
+   * @var string
+   */
+  const DRAFT_ENABLED_NONE = 'none';
+
+  /**
+   * Denote drafts are allowed for authenticated users only.
+   *
+   * @var string
+   */
+  const DRAFT_ENABLED_AUTHENTICATED = 'authenticated';
+
+  /**
+   * Denote drafts are allowed for authenticated and anonymous users.
+   *
+   * @var string
+   */
+  const DRAFT_ENABLED_ALL = 'authenticated_and_anonymous';
+
+  /**
    * Determine if the webform has page or is attached to other entities.
    *
    * @return bool
diff --git a/src/WebformSubmissionForm.php b/src/WebformSubmissionForm.php
index 6b7c8ce8..31516812 100644
--- a/src/WebformSubmissionForm.php
+++ b/src/WebformSubmissionForm.php
@@ -1365,8 +1365,25 @@ class WebformSubmissionForm extends ContentEntityForm {
    *   TRUE if drafts are enabled.
    */
   protected function draftEnabled() {
-    $account = $this->currentUser();
-    return ($account->isAuthenticated() && $this->getWebformSetting('draft') && !$this->getWebformSetting('results_disabled')) ? TRUE : FALSE;
+    if ($this->getWebformSetting('results_disabled')) {
+      return FALSE;
+    }
+    switch ($this->getWebformSetting('draft')) {
+      case WebformInterface::DRAFT_ENABLED_ALL:
+        return TRUE;
+        break;
+
+      case WebformInterface::DRAFT_ENABLED_AUTHENTICATED:
+        /** @var WebformSubmissionInterface $webform_submission */
+        $webform_submission = $this->getEntity();
+        return $webform_submission->getOwner()->isAuthenticated();
+        break;
+
+      case WebformInterface::DRAFT_ENABLED_NONE:
+      default:
+        return FALSE;
+        break;
+    }
   }
 
   /**
diff --git a/src/WebformSubmissionStorage.php b/src/WebformSubmissionStorage.php
index a8ab76b8..2ad8f24d 100644
--- a/src/WebformSubmissionStorage.php
+++ b/src/WebformSubmissionStorage.php
@@ -2,11 +2,19 @@
 
 namespace Drupal\webform;
 
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Language\LanguageManagerInterface;
 use Drupal\Core\Serialization\Yaml;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
 use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Session\AccountProxyInterface;
+use Drupal\user\UserInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Defines the webform submission storage.
@@ -21,6 +29,33 @@ class WebformSubmissionStorage extends SqlContentEntityStorage implements Webfor
   protected $elementDataSchema = [];
 
   /**
+   * Account proxy.
+   *
+   * @var \Drupal\Core\Session\AccountProxyInterface
+   */
+  protected $accountProxy;
+
+  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
+    return new static(
+      $entity_type,
+      $container->get('database'),
+      $container->get('entity.manager'),
+      $container->get('cache.entity'),
+      $container->get('language_manager'),
+      $container->get('current_user')
+    );
+  }
+
+  /**
+   * WebformSubmissionStorage constructor.
+   */
+  public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, AccountProxyInterface $account_proxy) {
+    parent::__construct($entity_type, $database, $entity_manager, $cache, $language_manager);
+
+    $this->accountProxy = $account_proxy;
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function getFieldDefinitions() {
@@ -51,6 +86,22 @@ class WebformSubmissionStorage extends SqlContentEntityStorage implements Webfor
     $query->condition('in_draft', TRUE);
     $query->condition('webform_id', $webform->id());
     $query->condition('uid', $account->id());
+    if ($account->isAnonymous()) {
+      // Anonymous drafts are additionally filtered by the token column.
+      $is_current_account = $account->id() == $this->accountProxy->id();
+      if (!$is_current_account) {
+        // We cannot clearly identify an anonymous user when it's not current
+        // one since we need session for anonymous user identification.
+        return NULL;
+      }
+
+      $drafts = $this->getAccountDraftTokens();
+      if (empty($drafts)) {
+        // This guy hasn't saved any draft.
+        return NULL;
+      }
+      $query->condition('token', $drafts, 'IN');
+    }
     if ($source_entity) {
       $query->condition('entity_type', $source_entity->getEntityTypeId());
       $query->condition('entity_id', $source_entity->id());
@@ -70,6 +121,28 @@ class WebformSubmissionStorage extends SqlContentEntityStorage implements Webfor
   /**
    * {@inheritdoc}
    */
+  public function accountLoggedIn(UserInterface $account) {
+    $draft_tokens = $this->getAccountDraftTokens();
+
+    // Move all anonymous drafts to UID of this account.
+    if (!empty($draft_tokens)) {
+      $query = $this->getQuery();
+      $query->condition('token', $draft_tokens, 'IN');
+      $query->condition('in_draft', 1);
+      $query->condition('uid', 0);
+      $ids = array_values($query->execute());
+      if (!empty($ids)) {
+        foreach ($this->loadMultiple($ids) as $webform_submission) {
+          $webform_submission->setOwner($account);
+          $webform_submission->save();
+        }
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   protected function doCreate(array $values) {
     /** @var \Drupal\webform\WebformSubmissionInterface $entity */
     $entity = parent::doCreate($values);
@@ -510,6 +583,15 @@ class WebformSubmissionStorage extends SqlContentEntityStorage implements Webfor
     $id = parent::doPreSave($entity);
     $this->invokeWebformElements('preSave', $entity);
     $this->invokeWebformHandlers('preSave', $entity);
+
+    // We watch out for privacy: if the submission owner UID does not match the
+    // current user, then we cannot work on current user's private temp storage
+    // since apparently it is another user. Probably it's an programmatic
+    // submission or god knows what.
+    if ($entity->getOwnerId() == $this->accountProxy->id() && $entity->isDraft() && $entity->getOwner()->isAnonymous()) {
+      $this->addAccountDraft($entity);
+    }
+
     return $id;
   }
 
@@ -855,4 +937,36 @@ class WebformSubmissionStorage extends SqlContentEntityStorage implements Webfor
       ->execute();
   }
 
+  /**
+   * Retrieve a list of webform submission tokens of a current account.
+   *
+   * We use session for storing draft tokens. So we can only do it for the
+   * current user.
+   *
+   * We do not use PrivateTempStore because it utilizes session ID as the key in
+   * key-value hash map where it stores its data. During user login the session
+   * ID is regenerated (see user_login_finalize()) so it is not suitable for us
+   * since we need to "carry" the draft tokens from anonmyous session to the
+   * logged in one. See self::accountLoggedIn() for additional details.
+   *
+   * @return string[]
+   *   Array of draft tokens of the provied account
+   */
+  protected function getAccountDraftTokens() {
+    return isset($_SESSION['webform']['draft_tokens']) ? $_SESSION['webform']['draft_tokens'] : [];
+  }
+
+  /**
+   * Add webform submission as a draft for the current account.
+   *
+   * @param \Drupal\webform\WebformSubmissionInterface $webform_submission
+   *   Webform submission to add as a draft of the current account
+   */
+  protected function addAccountDraft(WebformSubmissionInterface $webform_submission) {
+    if (!isset($_SESSION['webform']['draft_tokens'])) {
+      $_SESSION['webform']['draft_tokens'] = [];
+    }
+    $_SESSION['webform']['draft_tokens'][] = $webform_submission->getToken();
+  }
+
 }
diff --git a/src/WebformSubmissionStorageInterface.php b/src/WebformSubmissionStorageInterface.php
index 7c20ccc0..4e2980b7 100644
--- a/src/WebformSubmissionStorageInterface.php
+++ b/src/WebformSubmissionStorageInterface.php
@@ -5,6 +5,7 @@ namespace Drupal\webform;
 use Drupal\Core\Entity\ContentEntityStorageInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Session\AccountInterface;
+use Drupal\user\UserInterface;
 
 /**
  * Defines an interface for webform submission classes.
@@ -102,6 +103,14 @@ interface WebformSubmissionStorageInterface extends ContentEntityStorageInterfac
   public function loadDraft(WebformInterface $webform, EntityInterface $source_entity = NULL, AccountInterface $account = NULL);
 
   /**
+   * React to an event when a user logs in.
+   *
+   * @param \Drupal\user\UserInterface $account
+   *   Account that has just logged in
+   */
+  public function accountLoggedIn(UserInterface $account);
+
+  /**
    * Get the total number of submissions.
    *
    * @param \Drupal\webform\WebformInterface|null $webform
diff --git a/webform.module b/webform.module
index 10120cd0..b1340e7f 100644
--- a/webform.module
+++ b/webform.module
@@ -98,6 +98,14 @@ function webform_modules_uninstalled($modules) {
 }
 
 /**
+ * Implements hook_user_login().
+ */
+function webform_user_login($account) {
+  // Notify the storage of this log in.
+  \Drupal::entityTypeManager()->getStorage('webform_submission')->accountLoggedIn($account);
+}
+
+/**
  * Implements hook_cron().
  */
 function webform_cron() {
