diff --git a/include/class.auth.php b/include/class.auth.php
index 1dc5a9ccf8f05172bd081929dfcb4d50c4104fa8..cf1866a4ce32bb4d321299ad3e0a41149e082818 100644
--- a/include/class.auth.php
+++ b/include/class.auth.php
@@ -1313,7 +1313,35 @@ abstract class PasswordPolicy {
     static function register($policy) {
         static::$registry[] = $policy;
     }
+
+    static function cleanSessions($model, $user=null) {
+        $criteria = array();
+
+        switch (true) {
+            case ($model instanceof Staff):
+                $criteria['user_id'] = $model->getId();
+
+                if ($user && ($model->getId() == $user->getId()))
+                    array_push($criteria,
+                        Q::not(array('session_id' => $user->session->session_id)));
+                break;
+            case ($model instanceof User):
+                $regexp = '_auth\|.*"user";[a-z]+:[0-9]+:{[a-z]+:[0-9]+:"id";[a-z]+:'.$model->getId();
+                $criteria['user_id'] = 0;
+                $criteria['session_data__regex'] = $regexp;
+
+                if ($user)
+                    array_push($criteria,
+                        Q::not(array('session_id' => $user->session->session_id)));
+                break;
+            default:
+                return false;
+        }
+
+        return SessionData::objects()->filter($criteria)->delete();
+    }
 }
+Signal::connect('auth.clean', array('PasswordPolicy', 'cleanSessions'));
 
 class osTicketPasswordPolicy
 extends PasswordPolicy {
diff --git a/include/class.client.php b/include/class.client.php
index 53b6376c98ce603b76251ec6d4295fa88d91b2b8..bcf3c4257f8a2c0d2e4222b2ba4beb66b78e005c 100644
--- a/include/class.client.php
+++ b/include/class.client.php
@@ -396,7 +396,7 @@ class ClientAccount extends UserAccount {
         global $cfg;
 
         // FIXME: Updates by agents should go through UserAccount::update()
-        global $thisstaff;
+        global $thisstaff, $thisclient;
         if ($thisstaff)
             return parent::update($vars, $errors);
 
@@ -454,6 +454,8 @@ class ClientAccount extends UserAccount {
             Signal::send('auth.pwchange', $this->getUser(), $info);
             $this->cancelResetTokens();
             $this->clearStatus(UserAccountStatus::REQUIRE_PASSWD_RESET);
+            // Clean sessions
+            Signal::send('auth.clean', $this->getUser(), $thisclient);
         }
 
         return $this->save();
diff --git a/include/class.staff.php b/include/class.staff.php
index e5ed7e77555e5bb72f1376d10de92bc9b579569d..941f8baba2abd7849ed3c3d9036be434de26b3d7 100644
--- a/include/class.staff.php
+++ b/include/class.staff.php
@@ -217,6 +217,8 @@ implements AuthenticatedUser, EmailContact, TemplateVariable {
     }
 
     function setPassword($new, $current=false) {
+        global $thisstaff;
+
         // Allow the backend to update the password. This is the preferred
         // method as it allows for integration with password policies and
         // also allows for remotely updating the password where possible and
@@ -241,6 +243,9 @@ implements AuthenticatedUser, EmailContact, TemplateVariable {
         $this->cancelResetTokens();
         $this->passwdreset = SqlFunction::NOW();
 
+        // Clean sessions
+        Signal::send('auth.clean', $this, $thisstaff);
+
         return $rv;
     }
 
diff --git a/include/class.user.php b/include/class.user.php
index f0d5f235d85f14dd2d55efec6590c814f74d3b1d..e16259ce7e30f50ba15d619de90a24de4f6924f8 100644
--- a/include/class.user.php
+++ b/include/class.user.php
@@ -1033,6 +1033,8 @@ class UserAccount extends VerySimpleModel {
 
     function setPassword($new) {
         $this->set('passwd', Passwd::hash($new));
+        // Clean sessions
+        Signal::send('auth.clean', $this->getUser());
     }
 
     protected function sendUnlockEmail($template) {