Skip to content

Commit

Permalink
Unit tests for new auth behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasbestle committed Oct 17, 2022
1 parent 411996d commit 303f37c
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 15 deletions.
109 changes: 94 additions & 15 deletions tests/Cms/Auth/AuthChallengeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

namespace Kirby\Cms;

use Kirby\Cms\Auth\ErrorneousChallenge;
use Kirby\Email\Email;
use Kirby\Filesystem\Dir;

require_once __DIR__ . '/../mocks.php';
require_once __DIR__ . '/mocks.php';

/**
* @coversDefaultClass \Kirby\Cms\Auth
Expand All @@ -16,10 +18,11 @@ class AuthChallengeTest extends TestCase

protected $app;
protected $auth;
protected $fixtures;
protected $tmp;

public function setUp(): void
{
Auth::$challenges['errorneous'] = ErrorneousChallenge::class;
Email::$debug = true;
Email::$emails = [];
$_SERVER['SERVER_NAME'] = 'kirby.test';
Expand All @@ -34,12 +37,13 @@ public function setUp(): void
],
'options' => [
'auth' => [
'debug' => true,
'trials' => 2
'challenges' => ['errorneous', 'email'],
'debug' => true,
'trials' => 3
]
],
'roots' => [
'index' => $this->fixtures = __DIR__ . '/fixtures/AuthTest'
'index' => $this->tmp = __DIR__ . '/tmp'
],
'users' => [
[
Expand All @@ -48,28 +52,36 @@ public function setUp(): void
'password' => password_hash('springfield123', PASSWORD_DEFAULT)
],
[
'email' => 'test@exämple.com'
'email' => 'test@exämple.com',
'id' => 'idn'
],
[
'email' => 'error@getkirby.com',
'id' => 'error'
]
]
]);
Dir::make($this->fixtures . '/site/accounts');
Dir::make($this->tmp . '/site/accounts');

$this->auth = new Auth($this->app);
}

public function tearDown(): void
{
$this->app->session()->destroy();
Dir::remove($this->fixtures);
Dir::remove($this->tmp);

unset(Auth::$challenges['errorneous']);
Email::$debug = false;
Email::$emails = [];
unset($_SERVER['SERVER_NAME']);
$this->failedEmail = null;
}

/**
* @covers ::checkRateLimit
* @covers ::createChallenge
* @covers ::fail
* @covers ::status
*/
public function testCreateChallenge()
Expand Down Expand Up @@ -115,31 +127,70 @@ public function testCreateChallenge()
$this->assertNull($session->get('kirby.challenge.type'));
$this->assertSame('invalid@example.com', $this->failedEmail);

// error in the challenge
$status = $auth->createChallenge('error@getkirby.com');
$this->assertSame([
'challenge' => 'email',
'email' => 'error@getkirby.com',
'status' => 'pending'
], $status->toArray());
$this->assertNull($status->challenge(false));
$this->assertSame('error@getkirby.com', $session->get('kirby.challenge.email'));
$this->assertNull($session->get('kirby.challenge.type'));
$this->assertSame(MockTime::$time + 600, $session->get('kirby.challenge.timeout'));
$this->assertSame('invalid@example.com', $this->failedEmail); // a challenge error is not considered a failed login

// verify rate-limiting log
$data = [
'by-ip' => [
'87084f11690867b977a611dd2c943a918c3197f4c02b25ab59' => [
'time' => MockTime::$time,
'trials' => 2
'trials' => 3
]
],
'by-email' => [
'marge@simpsons.com' => [
'time' => MockTime::$time,
'trials' => 1
],
'error@getkirby.com' => [
'time' => MockTime::$time,
'trials' => 1
]
]
];
$this->assertSame($data, $auth->log());

// cannot create challenge when rate-limited
$this->expectException('Kirby\Exception\PermissionException');
$this->expectExceptionMessage('Invalid login');
$auth->createChallenge('marge@simpsons.com');
// fake challenge when rate-limited
$status = $auth->createChallenge('marge@simpsons.com');
$this->assertSame([
'challenge' => 'email',
'email' => 'marge@simpsons.com',
'status' => 'pending'
], $status->toArray());
$this->assertNull($status->challenge(false));
$this->assertSame('marge@simpsons.com', $session->get('kirby.challenge.email'));
$this->assertNull($session->get('kirby.challenge.type'));
$this->assertSame(MockTime::$time + 600, $session->get('kirby.challenge.timeout'));
$this->assertSame('marge@simpsons.com', $this->failedEmail);
}

/**
* @covers ::createChallenge
* @covers ::fail
*/
public function testCreateChallengeDebugError()
{
$auth = $this->app->auth();

$this->expectException('Exception');
$this->expectExceptionMessage('An error occurred in the challenge');
$auth->createChallenge('error@getkirby.com');
}

/**
* @covers ::createChallenge
* @covers ::fail
*/
public function testCreateChallengeDebugNotFound()
{
Expand All @@ -150,7 +201,9 @@ public function testCreateChallengeDebugNotFound()
}

/**
* @covers ::checkRateLimit
* @covers ::createChallenge
* @covers ::fail
*/
public function testCreateChallengeDebugRateLimit()
{
Expand All @@ -161,6 +214,7 @@ public function testCreateChallengeDebugRateLimit()
]);
$auth = $this->app->auth();

$auth->createChallenge('marge@simpsons.com');
$auth->createChallenge('marge@simpsons.com');
$auth->createChallenge('marge@simpsons.com');

Expand All @@ -171,6 +225,7 @@ public function testCreateChallengeDebugRateLimit()

/**
* @covers ::createChallenge
* @covers ::fail
* @covers ::status
*/
public function testCreateChallengeCustomTimeout()
Expand Down Expand Up @@ -239,20 +294,32 @@ public function testCreateChallengeWithPunycodeEmail()
*/
public function testEnabledChallenges()
{
$this->assertSame(['email'], $this->auth->enabledChallenges());
// default
$app = $this->app->clone([
'options' => [
'auth' => [
'challenges' => null
]
]
]);
$this->assertSame(['email'], $app->auth()->enabledChallenges());

// a single challenge
$app = $this->app->clone([
'options' => [
'auth.challenges' => 'totp'
'auth' => [
'challenges' => 'totp'
]
]
]);
$this->assertSame(['totp'], $app->auth()->enabledChallenges());

// multiple challenges
$app = $this->app->clone([
'options' => [
'auth.challenges' => ['totp', 'sms']
'auth' => [
'challenges' => ['totp', 'sms']
]
]
]);
$this->assertSame(['totp', 'sms'], $app->auth()->enabledChallenges());
Expand Down Expand Up @@ -307,6 +374,7 @@ public function testLogin2faLong()
}

/**
* @covers ::fail
* @covers ::login2fa
*/
public function testLogin2faInvalidUser()
Expand All @@ -319,6 +387,7 @@ public function testLogin2faInvalidUser()
}

/**
* @covers ::fail
* @covers ::login2fa
*/
public function testLogin2faInvalidPassword()
Expand Down Expand Up @@ -350,6 +419,7 @@ public function testVerifyChallenge()
}

/**
* @covers ::fail
* @covers ::verifyChallenge
*/
public function testVerifyChallengeNoChallenge1()
Expand All @@ -361,6 +431,7 @@ public function testVerifyChallengeNoChallenge1()
}

/**
* @covers ::fail
* @covers ::verifyChallenge
*/
public function testVerifyChallengeNoChallenge2()
Expand All @@ -373,6 +444,7 @@ public function testVerifyChallengeNoChallenge2()
}

/**
* @covers ::fail
* @covers ::verifyChallenge
*/
public function testVerifyChallengeNoChallengeNoDebug()
Expand All @@ -393,6 +465,7 @@ public function testVerifyChallengeNoChallengeNoDebug()
}

/**
* @covers ::fail
* @covers ::verifyChallenge
*/
public function testVerifyChallengeInvalidEmail()
Expand All @@ -406,6 +479,8 @@ public function testVerifyChallengeInvalidEmail()
}

/**
* @covers ::checkRateLimit
* @covers ::fail
* @covers ::verifyChallenge
*/
public function testVerifyChallengeRateLimited()
Expand All @@ -417,6 +492,7 @@ public function testVerifyChallengeRateLimited()

$this->auth->track('marge@simpsons.com');
$this->auth->track('homer@simpsons.com');
$this->auth->track('homer@simpsons.com');
$session->set('kirby.challenge.email', 'marge@simpsons.com');
$session->set('kirby.challenge.code', password_hash('123456', PASSWORD_DEFAULT));
$session->set('kirby.challenge.type', 'email');
Expand All @@ -425,6 +501,7 @@ public function testVerifyChallengeRateLimited()
}

/**
* @covers ::fail
* @covers ::verifyChallenge
*/
public function testVerifyChallengeTimeLimited()
Expand All @@ -443,6 +520,7 @@ public function testVerifyChallengeTimeLimited()
}

/**
* @covers ::fail
* @covers ::verifyChallenge
*/
public function testVerifyChallengeInvalidCode()
Expand All @@ -461,6 +539,7 @@ public function testVerifyChallengeInvalidCode()
}

/**
* @covers ::fail
* @covers ::verifyChallenge
*/
public function testVerifyChallengeInvalidChallenge()
Expand Down
7 changes: 7 additions & 0 deletions tests/Cms/Auth/AuthProtectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ public function testValidatePasswordValid()
}

/**
* @covers ::fail
* @covers ::validatePassword
*/
public function testValidatePasswordInvalid1()
Expand All @@ -232,6 +233,7 @@ public function testValidatePasswordInvalid1()
}

/**
* @covers ::fail
* @covers ::validatePassword
*/
public function testValidatePasswordInvalid2()
Expand All @@ -255,6 +257,7 @@ public function testValidatePasswordInvalid2()
}

/**
* @covers ::fail
* @covers ::validatePassword
*/
public function testValidatePasswordBlocked()
Expand All @@ -276,6 +279,7 @@ public function testValidatePasswordBlocked()
}

/**
* @covers ::fail
* @covers ::validatePassword
*/
public function testValidatePasswordDebugInvalid1()
Expand Down Expand Up @@ -306,6 +310,7 @@ public function testValidatePasswordDebugInvalid1()
}

/**
* @covers ::fail
* @covers ::validatePassword
*/
public function testValidatePasswordDebugInvalid2()
Expand Down Expand Up @@ -337,6 +342,8 @@ public function testValidatePasswordDebugInvalid2()
}

/**
* @covers ::checkRateLimit
* @covers ::fail
* @covers ::validatePassword
*/
public function testValidatePasswordDebugBlocked()
Expand Down
19 changes: 19 additions & 0 deletions tests/Cms/Auth/mocks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Kirby\Cms\Auth;

use Exception;
use Kirby\Cms\User;

class ErrorneousChallenge extends Challenge
{
public static function isAvailable(User $user, string $mode): bool
{
return $user->email() === 'error@getkirby.com';
}

public static function create(User $user, array $options): ?string
{
throw new Exception('An error occurred in the challenge');
}
}

0 comments on commit 303f37c

Please sign in to comment.