Log out with a POST form.
The logout link put the CSRF token in the URL, which goes into logs and the browser history.
This commit is contained in:
@@ -85,7 +85,9 @@ class FrontPagesTest extends PageTestCase {
|
||||
$token = $this->loginAs();
|
||||
$body = $this->get('/')['body'];
|
||||
$this->assertStringContainsString('Secret', $body);
|
||||
$this->assertStringContainsString('<a href="/publish/logout?token=' . $token . '">Logout</a>', $body);
|
||||
$this->assertStringContainsString('<form action="/publish/logout" method="post"><input type="hidden" name="csrf_token" value="' . $token . '" />'
|
||||
. '<button type="submit">Logout</button></form>', $body);
|
||||
$this->assertStringNotContainsString('?token=', $body);
|
||||
$this->assertStringContainsString('<a href="/publish/addeditor">Add editor</a>', $body);
|
||||
}
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ class LoginTest extends PageTestCase {
|
||||
// A new browser session with only the cookie
|
||||
unset($this->cookies['PHPSESSID']);
|
||||
$body = $this->get('/')['body'];
|
||||
$this->assertStringContainsString('/publish/logout?token=', $body);
|
||||
$this->assertStringContainsString('<form action="/publish/logout" method="post">', $body);
|
||||
$this->assertSame('ed', $this->session()['editor']);
|
||||
}
|
||||
|
||||
@@ -224,7 +224,15 @@ class LoginTest extends PageTestCase {
|
||||
|
||||
public function testLogoutNeedsTheToken(): void {
|
||||
$this->loginAs();
|
||||
$this->assertRedirect('/', $this->get('/publish/logout?token=wrong'));
|
||||
$this->assertRedirect('/', $this->post('/publish/logout', array('csrf_token' => 'wrong')));
|
||||
$this->assertSame('ed', $this->session()['editor']);
|
||||
}
|
||||
|
||||
// The token stays out of URLs, which go into logs and the browser history
|
||||
public function testLogoutNeedsAPost(): void {
|
||||
$token = $this->loginAs();
|
||||
$this->assertRedirect('/', $this->get('/publish/logout?token=' . $token));
|
||||
$this->assertRedirect('/', $this->get('/publish/logout?csrf_token=' . $token));
|
||||
$this->assertSame('ed', $this->session()['editor']);
|
||||
}
|
||||
|
||||
@@ -236,7 +244,7 @@ class LoginTest extends PageTestCase {
|
||||
$this->cookies['PersistentAuth'] = 'ed|key';
|
||||
$session = self::$state . '/sessions/sess_' . $this->cookies['PHPSESSID'];
|
||||
|
||||
$answer = $this->get('/publish/logout?token=' . $token);
|
||||
$answer = $this->post('/publish/logout', array('csrf_token' => $token));
|
||||
$this->assertRedirect('/article?id=2', $answer);
|
||||
$this->assertFileDoesNotExist($session);
|
||||
$this->assertArrayNotHasKey('PHPSESSID', $this->cookies);
|
||||
@@ -247,17 +255,17 @@ class LoginTest extends PageTestCase {
|
||||
public function testAForgedHostDoesNotMoveTheLogoutRedirect(): void {
|
||||
$token = $this->loginAs('ed', array('referrer' => '/article?id=2'));
|
||||
$this->assertRedirect('/article?id=2',
|
||||
$this->get('/publish/logout?token=' . $token, array('Host' => 'evil.example')));
|
||||
$this->post('/publish/logout', array('csrf_token' => $token), array('Host' => 'evil.example')));
|
||||
}
|
||||
|
||||
#[DataProvider('otherSites')]
|
||||
public function testLogoutIgnoresALastPageOnAnotherSite(string $referrer): void {
|
||||
$token = $this->loginAs('ed', array('referrer' => $referrer));
|
||||
$this->assertRedirect('/', $this->get('/publish/logout?token=' . $token));
|
||||
$this->assertRedirect('/', $this->post('/publish/logout', array('csrf_token' => $token)));
|
||||
}
|
||||
|
||||
public function testLogoutDoesNotGoBackToTheLogoutPage(): void {
|
||||
$token = $this->loginAs('ed', array('referrer' => '/publish/logout'));
|
||||
$this->assertRedirect('/', $this->get('/publish/logout?token=' . $token));
|
||||
$this->assertRedirect('/', $this->post('/publish/logout', array('csrf_token' => $token)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user