Browse Source

Invalidate sessions on password change; closes #170

tags/0.8.0
J. King 1 month ago
parent
commit
422eaf9605
4 changed files with 26 additions and 5 deletions
  1. 2
    1
      CHANGELOG
  2. 10
    4
      lib/Database.php
  3. 4
    0
      lib/User.php
  4. 10
    0
      tests/cases/Database/SeriesSession.php

+ 2
- 1
CHANGELOG View File

@@ -5,13 +5,14 @@ New features:
- Support for the Fever protocol (see README.md for details)
- Command line functionality for clearing a password, disabling the account
- Command line options for dealing with Fever passwords
- Command line functionality for exporting subscriptions to OPML
- Command line functionality for importing and exporting OPML
- Command line functionality for cron-based feed updating
- Command line documentation of all commands and options

Bug fixes:
- Treat command line option -h the same as --help
- Sort Tiny Tiny RSS special feeds according to special ordering
- Invalidate sessions when passwords are changed

Version 0.7.1 (2019-03-25)
==========================

+ 10
- 4
lib/Database.php View File

@@ -340,15 +340,21 @@ class Database {
* This function can be used to explicitly invalidate a session after a user logs out
*
* @param string $user The user who owns the session to be destroyed
* @param string $id The identifier of the session to destroy
* @param string|null $id The identifier of the session to destroy
*/
public function sessionDestroy(string $user, string $id): bool {
public function sessionDestroy(string $user, string $id = null): bool {
// If the user isn't authorized to perform this action then throw an exception.
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
}
// delete the session and report success.
return (bool) $this->db->prepare("DELETE FROM arsse_sessions where id = ? and \"user\" = ?", "str", "str")->run($id, $user)->changes();
if (is_null($id)) {
// delete all sessions and report success unconditionally if no identifier was specified
$this->db->prepare("DELETE FROM arsse_sessions where \"user\" = ?", "str")->run($user);
return true;
} else {
// otherwise delete only the specified session and report success.
return (bool) $this->db->prepare("DELETE FROM arsse_sessions where id = ? and \"user\" = ?", "str", "str")->run($id, $user)->changes();
}
}

/** Resumes a session, returning available session data

+ 4
- 0
lib/User.php View File

@@ -110,6 +110,8 @@ class User {
if (Arsse::$db->userExists($user)) {
// if the password change was successful and the user exists, set the internal password to the same value
Arsse::$db->userPasswordSet($user, $out);
// also invalidate any current sessions for the user
Arsse::$db->sessionDestroy($user);
}
return $out;
}
@@ -123,6 +125,8 @@ class User {
if (Arsse::$db->userExists($user)) {
// if the password change was successful and the user exists, set the internal password to the same value
Arsse::$db->userPasswordSet($user, null);
// also invalidate any current sessions for the user
Arsse::$db->sessionDestroy($user);
}
return $out;
}

+ 10
- 0
tests/cases/Database/SeriesSession.php View File

@@ -116,6 +116,16 @@ trait SeriesSession {
$this->assertFalse(Arsse::$db->sessionDestroy($user, $id));
}

public function testDestroyAllSessions() {
$user = "jane.doe@example.com";
$this->assertTrue(Arsse::$db->sessionDestroy($user));
$state = $this->primeExpectations($this->data, ['arsse_sessions' => ["id", "created", "expires", "user"]]);
unset($state['arsse_sessions']['rows'][0]);
unset($state['arsse_sessions']['rows'][1]);
unset($state['arsse_sessions']['rows'][2]);
$this->compareExpectations(static::$drv, $state);
}

public function testDestroyASessionForTheWrongUser() {
$user = "john.doe@example.com";
$id = "80fa94c1a11f11e78667001e673b2560";

Loading…
Cancel
Save