From c0f6463d57ab41b346804235088e1752b623cad3 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Thu, 3 Dec 2020 18:33:19 +0100 Subject: [PATCH] new: [security] Cancel API session right after auth key is deleted --- app/Controller/AppController.php | 6 ++++++ app/Model/AuthKey.php | 12 ++++++++++++ tests/testlive_security.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/app/Controller/AppController.php b/app/Controller/AppController.php index 5e46d7493..9c96b6b32 100755 --- a/app/Controller/AppController.php +++ b/app/Controller/AppController.php @@ -1420,6 +1420,12 @@ class AppController extends Controller if (!$user) { throw new RuntimeException("User with ID {$sessionUser['id']} not exists."); } + if (isset($sessionUser['authkey_id'])) { + $this->loadModel('AuthKey'); + if (!$this->AuthKey->exists($sessionUser['authkey_id'])) { + throw new RuntimeException("Auth key with ID {$sessionUser['authkey_id']} not exists."); + } + } foreach (['authkey_id', 'authkey_expiration', 'logged_by_authkey'] as $copy) { if (isset($sessionUser[$copy])) { $user[$copy] = $sessionUser[$copy]; diff --git a/app/Model/AuthKey.php b/app/Model/AuthKey.php index 390973f85..06b115261 100644 --- a/app/Model/AuthKey.php +++ b/app/Model/AuthKey.php @@ -154,6 +154,18 @@ class AuthKey extends AppModel return [$output, $lastUsage]; } + /** + * When key is deleted, update after `date_modified` for user that was assigned to that key, so session data + * will be realoaded and canceled. + * @see AppController::_refreshAuth + */ + public function afterDelete() + { + parent::afterDelete(); + $userId = $this->data['AuthKey']['user_id']; + $this->User->updateAll(['date_modified' => time()], ['User.id' => $userId]); + } + /** * @return AbstractPasswordHasher */ diff --git a/tests/testlive_security.py b/tests/testlive_security.py index 30731d1c7..30dca3713 100644 --- a/tests/testlive_security.py +++ b/tests/testlive_security.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import os import sys +import time import json import datetime import unittest @@ -375,6 +376,35 @@ class TestSecurity(unittest.TestCase): self.__delete_advanced_authkey(auth_key["id"]) + def test_advanced_authkeys_deleted(self): + with MISPSetting(self.admin_misp_connector, "Security.advanced_authkeys", True): + auth_key = self.__create_advanced_authkey(self.test_usr.id) + + logged_in = PyMISP(url, auth_key["authkey_raw"]) + self.assertEqual(logged_in._current_user.id, self.test_usr.id) + + self.__delete_advanced_authkey(auth_key["id"]) + + assert_error_response(logged_in.get_user()) + + def test_advanced_authkeys_deleted_keep_session(self): + with MISPComplexSetting({ + "Security": { + "advanced_authkeys": True, + "authkey_keep_session": True, + } + }): + auth_key = self.__create_advanced_authkey(self.test_usr.id) + + logged_in = PyMISP(url, auth_key["authkey_raw"]) + self.assertEqual(logged_in._current_user.id, self.test_usr.id) + + self.__delete_advanced_authkey(auth_key["id"]) + # Wait one second to really know that session will be reloaded + time.sleep(1) + with self.assertRaises(MISPServerError): + logged_in.get_user() + def test_advanced_authkeys_own_key_not_possible(self): with MISPSetting(self.admin_misp_connector, "Security.advanced_authkeys", True): authkey = ("a" * 40)