appwrite/tests/unit/Auth/AuthTest.php

327 lines
14 KiB
PHP
Raw Normal View History

2019-12-28 16:37:39 +00:00
<?php
2022-08-01 10:22:04 +00:00
namespace Tests\Unit\Auth;
2019-12-28 16:37:39 +00:00
use Appwrite\Auth\Auth;
2024-03-06 17:34:21 +00:00
use PHPUnit\Framework\TestCase;
2025-03-18 21:12:03 +00:00
use Utopia\Auth\Proofs\Token;
use Utopia\Database\DateTime;
2021-10-07 19:19:58 +00:00
use Utopia\Database\Document;
2023-02-05 20:07:46 +00:00
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Role;
2021-10-07 19:27:23 +00:00
use Utopia\Database\Validator\Authorization;
2022-10-16 01:47:38 +00:00
use Utopia\Database\Validator\Roles;
2025-03-18 21:12:03 +00:00
2019-12-28 16:37:39 +00:00
class AuthTest extends TestCase
{
2021-10-07 20:24:09 +00:00
/**
* Reset Roles
*/
2020-09-30 21:08:58 +00:00
public function tearDown(): void
2019-12-28 16:37:39 +00:00
{
2024-10-08 07:54:40 +00:00
Authorization::cleanRoles();
Authorization::setRole(Role::any()->toString());
2019-12-28 16:37:39 +00:00
}
2022-05-23 14:54:50 +00:00
2022-08-01 10:22:04 +00:00
public function testSessionVerify(): void
2021-02-19 12:12:47 +00:00
{
2025-03-18 21:12:03 +00:00
$proofForToken = new Token();
2022-11-04 09:50:59 +00:00
$expireTime1 = 60 * 60 * 24;
2021-02-19 12:12:47 +00:00
$secret = 'secret1';
2025-03-18 21:12:03 +00:00
$hash = $proofForToken->hash($secret);
2021-02-19 12:12:47 +00:00
$tokens1 = [
new Document([
2022-08-14 10:33:36 +00:00
'$id' => ID::custom('token1'),
2021-02-19 12:12:47 +00:00
'secret' => $hash,
2025-03-17 20:44:31 +00:00
'provider' => SESSION_PROVIDER_EMAIL,
2021-02-19 12:12:47 +00:00
'providerUid' => 'test@example.com',
2024-01-15 14:53:37 +00:00
'expire' => DateTime::addSeconds(new \DateTime(), $expireTime1),
2021-02-19 12:12:47 +00:00
]),
new Document([
2022-08-14 10:33:36 +00:00
'$id' => ID::custom('token2'),
2021-02-19 12:12:47 +00:00
'secret' => 'secret2',
2025-03-17 20:44:31 +00:00
'provider' => SESSION_PROVIDER_EMAIL,
2021-02-19 12:12:47 +00:00
'providerUid' => 'test@example.com',
2024-01-15 14:53:37 +00:00
'expire' => DateTime::addSeconds(new \DateTime(), $expireTime1),
2021-02-19 12:12:47 +00:00
]),
];
2022-11-04 09:50:59 +00:00
$expireTime2 = -60 * 60 * 24;
2021-02-19 12:12:47 +00:00
$tokens2 = [
new Document([ // Correct secret and type time, wrong expire time
2022-08-14 10:33:36 +00:00
'$id' => ID::custom('token1'),
2021-02-19 12:12:47 +00:00
'secret' => $hash,
2025-03-17 20:44:31 +00:00
'provider' => SESSION_PROVIDER_EMAIL,
2021-02-19 12:12:47 +00:00
'providerUid' => 'test@example.com',
2024-01-15 14:53:37 +00:00
'expire' => DateTime::addSeconds(new \DateTime(), $expireTime2),
2021-02-19 12:12:47 +00:00
]),
new Document([
2022-08-14 10:33:36 +00:00
'$id' => ID::custom('token2'),
2021-02-19 12:12:47 +00:00
'secret' => 'secret2',
2025-03-17 20:44:31 +00:00
'provider' => SESSION_PROVIDER_EMAIL,
2021-02-19 12:12:47 +00:00
'providerUid' => 'test@example.com',
2024-01-15 14:53:37 +00:00
'expire' => DateTime::addSeconds(new \DateTime(), $expireTime2),
2021-02-19 12:12:47 +00:00
]),
];
2025-03-18 18:08:58 +00:00
$this->assertEquals(Auth::sessionVerify($tokens1, $secret, $proofForToken), 'token1');
$this->assertEquals(Auth::sessionVerify($tokens1, 'false-secret', $proofForToken), false);
$this->assertEquals(Auth::sessionVerify($tokens2, $secret, $proofForToken), false);
$this->assertEquals(Auth::sessionVerify($tokens2, 'false-secret', $proofForToken), false);
2021-02-19 12:12:47 +00:00
}
2022-08-01 10:22:04 +00:00
public function testTokenVerify(): void
2019-12-28 16:37:39 +00:00
{
2025-03-18 21:12:03 +00:00
$proofForToken = new Token();
2019-12-28 16:37:39 +00:00
$secret = 'secret1';
2025-03-18 21:12:03 +00:00
$hash = $proofForToken->hash($secret);
2019-12-28 16:37:39 +00:00
$tokens1 = [
new Document([
2022-08-14 10:33:36 +00:00
'$id' => ID::custom('token1'),
2025-03-17 20:44:31 +00:00
'type' => TOKEN_TYPE_RECOVERY,
2022-08-15 19:18:37 +00:00
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), 60 * 60 * 24)),
2019-12-28 16:37:39 +00:00
'secret' => $hash,
]),
new Document([
2022-08-14 10:33:36 +00:00
'$id' => ID::custom('token2'),
2025-03-17 20:44:31 +00:00
'type' => TOKEN_TYPE_RECOVERY,
2022-08-15 19:18:37 +00:00
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -60 * 60 * 24)),
2019-12-28 16:37:39 +00:00
'secret' => 'secret2',
]),
];
$tokens2 = [
new Document([ // Correct secret and type time, wrong expire time
2022-08-14 10:33:36 +00:00
'$id' => ID::custom('token1'),
2025-03-17 20:44:31 +00:00
'type' => TOKEN_TYPE_RECOVERY,
2022-08-15 19:18:37 +00:00
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -60 * 60 * 24)),
2019-12-28 16:37:39 +00:00
'secret' => $hash,
]),
new Document([
2022-08-14 10:33:36 +00:00
'$id' => ID::custom('token2'),
2025-03-17 20:44:31 +00:00
'type' => TOKEN_TYPE_RECOVERY,
2022-08-15 19:18:37 +00:00
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -60 * 60 * 24)),
2019-12-28 16:37:39 +00:00
'secret' => 'secret2',
]),
];
$tokens3 = [ // Correct secret and expire time, wrong type
new Document([
2022-08-14 10:33:36 +00:00
'$id' => ID::custom('token1'),
2025-03-17 20:44:31 +00:00
'type' => TOKEN_TYPE_INVITE,
2022-08-15 19:18:37 +00:00
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), 60 * 60 * 24)),
2019-12-28 16:37:39 +00:00
'secret' => $hash,
]),
new Document([
2022-08-14 10:33:36 +00:00
'$id' => ID::custom('token2'),
2025-03-17 20:44:31 +00:00
'type' => TOKEN_TYPE_RECOVERY,
2022-08-15 19:18:37 +00:00
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -60 * 60 * 24)),
2019-12-28 16:37:39 +00:00
'secret' => 'secret2',
]),
];
2025-03-18 21:12:03 +00:00
$this->assertEquals(Auth::tokenVerify($tokens1, TOKEN_TYPE_RECOVERY, $secret, $proofForToken), $tokens1[0]);
$this->assertEquals(Auth::tokenVerify($tokens1, null, $secret, $proofForToken), $tokens1[0]);
$this->assertEquals(Auth::tokenVerify($tokens1, TOKEN_TYPE_RECOVERY, 'false-secret', $proofForToken), false);
$this->assertEquals(Auth::tokenVerify($tokens2, TOKEN_TYPE_RECOVERY, $secret, $proofForToken), false);
$this->assertEquals(Auth::tokenVerify($tokens2, TOKEN_TYPE_RECOVERY, 'false-secret', $proofForToken), false);
$this->assertEquals(Auth::tokenVerify($tokens3, TOKEN_TYPE_RECOVERY, $secret, $proofForToken), false);
$this->assertEquals(Auth::tokenVerify($tokens3, TOKEN_TYPE_RECOVERY, 'false-secret', $proofForToken), false);
2019-12-28 16:37:39 +00:00
}
2020-11-20 06:48:25 +00:00
2022-08-01 10:22:04 +00:00
public function testIsPrivilegedUser(): void
2020-11-20 06:48:25 +00:00
{
2021-03-01 21:04:53 +00:00
$this->assertEquals(false, Auth::isPrivilegedUser([]));
2022-08-19 04:04:33 +00:00
$this->assertEquals(false, Auth::isPrivilegedUser([Role::guests()->toString()]));
$this->assertEquals(false, Auth::isPrivilegedUser([Role::users()->toString()]));
2025-03-17 20:44:31 +00:00
$this->assertEquals(true, Auth::isPrivilegedUser([USER_ROLE_ADMIN]));
$this->assertEquals(true, Auth::isPrivilegedUser([USER_ROLE_DEVELOPER]));
$this->assertEquals(true, Auth::isPrivilegedUser([USER_ROLE_OWNER]));
$this->assertEquals(false, Auth::isPrivilegedUser([USER_ROLE_APPS]));
$this->assertEquals(false, Auth::isPrivilegedUser([USER_ROLE_SYSTEM]));
$this->assertEquals(false, Auth::isPrivilegedUser([USER_ROLE_APPS, USER_ROLE_APPS]));
$this->assertEquals(false, Auth::isPrivilegedUser([USER_ROLE_APPS, Role::guests()->toString()]));
$this->assertEquals(true, Auth::isPrivilegedUser([USER_ROLE_OWNER, Role::guests()->toString()]));
$this->assertEquals(true, Auth::isPrivilegedUser([USER_ROLE_OWNER, USER_ROLE_ADMIN, USER_ROLE_DEVELOPER]));
2020-11-20 06:48:25 +00:00
}
2022-05-23 14:54:50 +00:00
2022-08-01 10:22:04 +00:00
public function testIsAppUser(): void
2020-11-20 06:48:25 +00:00
{
$this->assertEquals(false, Auth::isAppUser([]));
2022-08-19 04:04:33 +00:00
$this->assertEquals(false, Auth::isAppUser([Role::guests()->toString()]));
$this->assertEquals(false, Auth::isAppUser([Role::users()->toString()]));
2025-03-17 20:44:31 +00:00
$this->assertEquals(false, Auth::isAppUser([USER_ROLE_ADMIN]));
$this->assertEquals(false, Auth::isAppUser([USER_ROLE_DEVELOPER]));
$this->assertEquals(false, Auth::isAppUser([USER_ROLE_OWNER]));
$this->assertEquals(true, Auth::isAppUser([USER_ROLE_APPS]));
$this->assertEquals(false, Auth::isAppUser([USER_ROLE_SYSTEM]));
$this->assertEquals(true, Auth::isAppUser([USER_ROLE_APPS, USER_ROLE_APPS]));
$this->assertEquals(true, Auth::isAppUser([USER_ROLE_APPS, Role::guests()->toString()]));
$this->assertEquals(false, Auth::isAppUser([USER_ROLE_OWNER, Role::guests()->toString()]));
$this->assertEquals(false, Auth::isAppUser([USER_ROLE_OWNER, USER_ROLE_ADMIN, USER_ROLE_DEVELOPER]));
2020-11-20 06:48:25 +00:00
}
2021-06-29 13:11:14 +00:00
2022-08-01 10:22:04 +00:00
public function testGuestRoles(): void
2021-06-29 13:11:14 +00:00
{
$user = new Document([
'$id' => ''
]);
2024-10-08 07:54:40 +00:00
$roles = Auth::getRoles($user);
$this->assertCount(1, $roles);
2022-08-19 04:04:33 +00:00
$this->assertContains(Role::guests()->toString(), $roles);
2021-06-29 13:11:14 +00:00
}
2022-08-01 10:22:04 +00:00
public function testUserRoles(): void
2021-06-29 13:11:14 +00:00
{
$user = new Document([
2022-08-14 10:33:36 +00:00
'$id' => ID::custom('123'),
'labels' => [
'vip',
'admin'
],
2022-09-13 12:45:57 +00:00
'emailVerification' => true,
'phoneVerification' => true,
2021-06-29 13:11:14 +00:00
'memberships' => [
[
'$id' => ID::custom('456'),
2022-08-14 10:33:36 +00:00
'teamId' => ID::custom('abc'),
'confirm' => true,
2021-06-29 13:11:14 +00:00
'roles' => [
'administrator',
'moderator'
]
],
[
'$id' => ID::custom('abc'),
2022-08-14 10:33:36 +00:00
'teamId' => ID::custom('def'),
'confirm' => true,
2021-06-29 13:11:14 +00:00
'roles' => [
'guest'
]
]
]
]);
2024-10-08 07:54:40 +00:00
$roles = Auth::getRoles($user);
2021-06-29 13:11:14 +00:00
$this->assertCount(13, $roles);
2022-08-27 03:16:37 +00:00
$this->assertContains(Role::users()->toString(), $roles);
2022-08-27 04:06:38 +00:00
$this->assertContains(Role::user(ID::custom('123'))->toString(), $roles);
2022-10-14 11:23:20 +00:00
$this->assertContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles);
2022-08-27 04:06:38 +00:00
$this->assertContains(Role::team(ID::custom('abc'))->toString(), $roles);
$this->assertContains(Role::team(ID::custom('abc'), 'administrator')->toString(), $roles);
$this->assertContains(Role::team(ID::custom('abc'), 'moderator')->toString(), $roles);
$this->assertContains(Role::team(ID::custom('def'))->toString(), $roles);
$this->assertContains(Role::team(ID::custom('def'), 'guest')->toString(), $roles);
$this->assertContains(Role::member(ID::custom('456'))->toString(), $roles);
$this->assertContains(Role::member(ID::custom('abc'))->toString(), $roles);
$this->assertContains('label:vip', $roles);
$this->assertContains('label:admin', $roles);
2022-09-13 12:45:57 +00:00
// Disable all verification
$user['emailVerification'] = false;
$user['phoneVerification'] = false;
2024-10-08 07:54:40 +00:00
$roles = Auth::getRoles($user);
2022-10-14 11:23:20 +00:00
$this->assertContains(Role::users(Roles::DIMENSION_UNVERIFIED)->toString(), $roles);
$this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_UNVERIFIED)->toString(), $roles);
2022-09-13 12:45:57 +00:00
// Enable single verification type
$user['emailVerification'] = true;
2024-10-08 07:54:40 +00:00
$roles = Auth::getRoles($user);
2022-10-14 11:23:20 +00:00
$this->assertContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles);
2021-06-29 13:11:14 +00:00
}
2021-09-03 15:59:02 +00:00
2022-08-01 10:22:04 +00:00
public function testPrivilegedUserRoles(): void
2021-09-03 16:05:50 +00:00
{
2025-03-17 20:44:31 +00:00
Authorization::setRole(USER_ROLE_OWNER);
2021-09-03 16:05:50 +00:00
$user = new Document([
2022-08-14 10:33:36 +00:00
'$id' => ID::custom('123'),
2022-09-13 12:45:57 +00:00
'emailVerification' => true,
'phoneVerification' => true,
2021-09-03 16:05:50 +00:00
'memberships' => [
[
'$id' => ID::custom('def'),
2022-08-14 10:33:36 +00:00
'teamId' => ID::custom('abc'),
'confirm' => true,
2021-09-03 16:05:50 +00:00
'roles' => [
'administrator',
'moderator'
]
],
[
'$id' => ID::custom('abc'),
2022-08-14 10:33:36 +00:00
'teamId' => ID::custom('def'),
'confirm' => true,
2021-09-03 16:05:50 +00:00
'roles' => [
'guest'
]
]
]
]);
2024-10-08 07:54:40 +00:00
$roles = Auth::getRoles($user);
2021-09-03 16:05:50 +00:00
$this->assertCount(7, $roles);
2022-08-27 03:16:37 +00:00
$this->assertNotContains(Role::users()->toString(), $roles);
2022-08-27 04:06:38 +00:00
$this->assertNotContains(Role::user(ID::custom('123'))->toString(), $roles);
2022-10-14 11:23:20 +00:00
$this->assertNotContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertNotContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles);
2022-08-27 04:06:38 +00:00
$this->assertContains(Role::team(ID::custom('abc'))->toString(), $roles);
$this->assertContains(Role::team(ID::custom('abc'), 'administrator')->toString(), $roles);
$this->assertContains(Role::team(ID::custom('abc'), 'moderator')->toString(), $roles);
$this->assertContains(Role::team(ID::custom('def'))->toString(), $roles);
$this->assertContains(Role::team(ID::custom('def'), 'guest')->toString(), $roles);
$this->assertContains(Role::member(ID::custom('def'))->toString(), $roles);
$this->assertContains(Role::member(ID::custom('abc'))->toString(), $roles);
2021-09-03 16:05:50 +00:00
}
2022-08-01 10:22:04 +00:00
public function testAppUserRoles(): void
2021-09-03 15:59:02 +00:00
{
2025-03-17 20:44:31 +00:00
Authorization::setRole(USER_ROLE_APPS);
2021-09-03 15:59:02 +00:00
$user = new Document([
2022-08-14 10:33:36 +00:00
'$id' => ID::custom('123'),
2021-09-03 15:59:02 +00:00
'memberships' => [
[
'$id' => ID::custom('def'),
2022-08-14 10:33:36 +00:00
'teamId' => ID::custom('abc'),
'confirm' => true,
2021-09-03 15:59:02 +00:00
'roles' => [
'administrator',
'moderator'
]
],
[
'$id' => ID::custom('abc'),
2022-08-14 10:33:36 +00:00
'teamId' => ID::custom('def'),
'confirm' => true,
2021-09-03 15:59:02 +00:00
'roles' => [
'guest'
]
]
]
]);
2024-10-08 07:54:40 +00:00
$roles = Auth::getRoles($user);
2021-09-03 15:59:02 +00:00
$this->assertCount(7, $roles);
2022-08-27 03:16:37 +00:00
$this->assertNotContains(Role::users()->toString(), $roles);
2022-08-27 04:06:38 +00:00
$this->assertNotContains(Role::user(ID::custom('123'))->toString(), $roles);
$this->assertContains(Role::team(ID::custom('abc'))->toString(), $roles);
$this->assertContains(Role::team(ID::custom('abc'), 'administrator')->toString(), $roles);
$this->assertContains(Role::team(ID::custom('abc'), 'moderator')->toString(), $roles);
$this->assertContains(Role::team(ID::custom('def'))->toString(), $roles);
$this->assertContains(Role::team(ID::custom('def'), 'guest')->toString(), $roles);
$this->assertContains(Role::member(ID::custom('def'))->toString(), $roles);
$this->assertContains(Role::member(ID::custom('abc'))->toString(), $roles);
2021-09-03 15:59:02 +00:00
}
2020-09-30 21:08:58 +00:00
}